diff --git a/package.json b/package.json index b9234b229..52da909ff 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,8 @@ "msw": { "workerDirectory": [ "e2e", - "e2e/public" + "e2e/public", + "sdk-app/public" ] } } diff --git a/sdk-app/public/sample-documents/w9.pdf b/sdk-app/public/sample-documents/w9.pdf new file mode 100644 index 000000000..c5eb64678 Binary files /dev/null and b/sdk-app/public/sample-documents/w9.pdf differ diff --git a/sdk-app/src/Sidebar.module.scss b/sdk-app/src/Sidebar.module.scss index b57b91ff0..636665fa9 100644 --- a/sdk-app/src/Sidebar.module.scss +++ b/sdk-app/src/Sidebar.module.scss @@ -51,48 +51,6 @@ border-bottom: 0.0625rem solid var(--color-border); } -.shortcutHint { - display: flex; - align-items: center; - gap: 0.375rem; - width: 100%; - margin-bottom: 0.5rem; - padding: 0.25rem 0.5rem; - border: none; - border-radius: 0.25rem; - background: transparent; - font: inherit; - font-size: 0.6875rem; - text-align: left; - color: var(--color-text-muted); - cursor: pointer; - user-select: none; - - &:hover { - color: var(--color-text); - background: var(--color-hover-bg); - } - - &:focus-visible { - outline: 0.125rem solid var(--color-active); - outline-offset: 0.125rem; - } -} - -.shortcutHintKey { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 1.125rem; - padding: 0 0.3125rem; - border: 0.0625rem solid var(--color-border); - border-radius: 0.1875rem; - background: var(--color-badge-bg); - font-family: monospace; - font-size: 0.625rem; - color: var(--color-text); -} - .searchRow { display: flex; align-items: stretch; @@ -158,10 +116,8 @@ justify-content: space-between; padding: 0.5rem 1rem; cursor: pointer; - font-weight: 500; - font-size: 0.8rem; - color: var(--color-text-muted); user-select: none; + &:hover { color: var(--color-text); } @@ -173,14 +129,17 @@ border-radius: 0.625rem; font-size: 0.6875rem; font-weight: 500; + color: var(--color-text-muted); } .categoryTitle { display: inline-flex; align-items: center; gap: 0.375rem; - font-weight: 500; - font-size: 0.8rem; + font-size: 0.6875rem; + font-weight: 600; + letter-spacing: 0.05em; + text-transform: uppercase; color: var(--color-text-muted); } @@ -197,25 +156,47 @@ list-style: none; } -.item a { +.item > a { display: block; - padding: 0.375rem 1rem 0.375rem 1.75rem; + padding: 0.375rem 1rem 0.375rem 1.5rem; color: var(--color-text); text-decoration: none; font-size: 0.8125rem; - border-left: 0.1875rem solid transparent; + font-weight: 500; + transition: + background 0.1s, + color 0.1s; + + &:hover { + background: var(--color-hover-bg); + } + + &:global(.active) { + color: var(--color-active); + } +} + +.subItems { + list-style: none; + margin: 0; + padding: 0; +} + +.subItem a { + display: block; + padding: 0.3125rem 1rem 0.3125rem 2.25rem; + color: var(--color-text-muted); + text-decoration: none; + font-size: 0.75rem; transition: background 0.1s, - border-color 0.1s; + color 0.1s; &:hover { background: var(--color-hover-bg); } &:global(.active) { - background: var(--color-active-bg); - border-left-color: var(--color-active); color: var(--color-active); - font-weight: 500; } } diff --git a/sdk-app/src/Sidebar.tsx b/sdk-app/src/Sidebar.tsx index 8d3f1cb24..8b0cf5cf9 100644 --- a/sdk-app/src/Sidebar.tsx +++ b/sdk-app/src/Sidebar.tsx @@ -1,5 +1,5 @@ import { useState, useMemo } from 'react' -import { NavLink } from 'react-router-dom' +import { NavLink, useLocation } from 'react-router-dom' import { categorizedRegistry as previewRegistry, CATEGORIES as PREVIEW_CATEGORIES, @@ -21,6 +21,16 @@ interface SidebarProps { onShowShortcuts: () => void } +interface SidebarItem { + name: string + path?: string + children?: SidebarItem[] +} + +function isUnder(pathname: string, target: string): boolean { + return pathname === target || pathname.startsWith(`${target}/`) +} + const PREVIEW_CATEGORY_LABELS: Record = { InformationRequests: 'Info Requests', EmployeeManagement: 'Employee Management', @@ -38,16 +48,20 @@ function CategorySection({ mode, }: { category: string - items: { name: string; path?: string }[] + items: SidebarItem[] searchQuery: string mode: AppMode }) { const [collapsed, setCollapsed] = useState(false) + const { pathname } = useLocation() const filteredItems = useMemo(() => { if (!searchQuery) return items const q = searchQuery.toLowerCase() - return items.filter(item => item.name.toLowerCase().includes(q)) + return items.filter(item => { + if (item.name.toLowerCase().includes(q)) return true + return item.children?.some(child => child.name.toLowerCase().includes(q)) ?? false + }) }, [items, searchQuery]) if (searchQuery && filteredItems.length === 0) return null @@ -73,7 +87,6 @@ function CategorySection({ /> {displayCategory} - {filteredItems.length} {!collapsed && ( @@ -81,9 +94,43 @@ function CategorySection({ {filteredItems.map(item => { const to = mode === 'design' && item.path ? item.path : `/${category.toLowerCase()}/${item.name}` + const showChildren = + !!item.children?.length && !!item.path && isUnder(pathname, item.path) return (
  • - {item.name} + + {item.name} + + {showChildren && item.children && ( + + )}
  • ) })} @@ -93,14 +140,7 @@ function CategorySection({ ) } -export function Sidebar({ - mode, - searchQuery, - onSearchChange, - isOpen, - onToggle, - onShowShortcuts, -}: SidebarProps) { +export function Sidebar({ mode, searchQuery, onSearchChange, isOpen, onToggle }: SidebarProps) { const placeholder = mode === 'design' ? 'Search prototypes...' : 'Search components...' if (!isOpen) { @@ -122,14 +162,6 @@ export function Sidebar({ return (