From cbd4274a52c7beee1d6711cf2fd9dcc28b2b789d Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 29 May 2026 07:15:43 -0700 Subject: [PATCH] feat(tracker-web): adopt @bytelyst/ui AppShell nav shell (UX-8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hand-rolled sticky top nav in the dashboard layout with the shared AppShell (AppShellSidebar/AppShellNav/AppShellNavItem/AppShellMain/ AppShellSkipLink + mobile toggle + overlay). The sidebar keeps the ProductSwitcher, user email and Sign out, and adds a ⌘K trigger (replays the global hotkey) and a theme toggle. Nav items use aria-current for the active route and client-side navigation; the skip-link targets the focusable main region. AppShell exports are routed through the Primitives adapter (CC.6 ratchet) and covered by the export-presence test. AppShellPageHeader is intentionally not used so the per-page PageHeader (UX-10) remains the single h1 per route (no duplicate headings). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../primitives-adapter.exports.test.ts | 10 ++ .../tracker-web/src/app/dashboard/layout.tsx | 112 ++++++++++++------ .../src/components/ui/Primitives.tsx | 22 ++++ 3 files changed, 111 insertions(+), 33 deletions(-) diff --git a/dashboards/tracker-web/src/__tests__/primitives-adapter.exports.test.ts b/dashboards/tracker-web/src/__tests__/primitives-adapter.exports.test.ts index 231710cc..14b80472 100644 --- a/dashboards/tracker-web/src/__tests__/primitives-adapter.exports.test.ts +++ b/dashboards/tracker-web/src/__tests__/primitives-adapter.exports.test.ts @@ -83,6 +83,16 @@ const EXPECTED_EXPORTS = [ 'DataListItem', 'DataListMeta', 'Timeline', + // UX-8 AppShell additions + 'AppShell', + 'AppShellMain', + 'AppShellMobileToggle', + 'AppShellNav', + 'AppShellNavItem', + 'AppShellOverlay', + 'AppShellPageHeader', + 'AppShellSidebar', + 'AppShellSkipLink', ] as const; describe('Primitives adapter — export presence', () => { diff --git a/dashboards/tracker-web/src/app/dashboard/layout.tsx b/dashboards/tracker-web/src/app/dashboard/layout.tsx index 086598ca..0b35aa43 100644 --- a/dashboards/tracker-web/src/app/dashboard/layout.tsx +++ b/dashboards/tracker-web/src/app/dashboard/layout.tsx @@ -1,9 +1,21 @@ 'use client'; -import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useRouter, usePathname } from 'next/navigation'; import Link from 'next/link'; +import { + AppShell, + AppShellSkipLink, + AppShellMobileToggle, + AppShellOverlay, + AppShellSidebar, + AppShellNav, + AppShellNavItem, + AppShellMain, + Button, +} from '@/components/ui/Primitives'; import { useAuth } from '@/lib/auth-context'; +import { useTheme } from '@/lib/theme-context'; import { ProductSwitcher } from '@/components/product-switcher'; import { SystemBanners } from '@/components/system-banners'; @@ -13,9 +25,17 @@ const NAV_ITEMS = [ { href: '/dashboard/board', label: 'Board' }, ]; +/** Open the ⌘K command palette by replaying the global hotkey. */ +function openCommandPalette() { + window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true, ctrlKey: true })); +} + export default function DashboardLayout({ children }: { children: React.ReactNode }) { const { user, loading, logout } = useAuth(); + const { theme, setTheme } = useTheme(); const router = useRouter(); + const pathname = usePathname(); + const [navOpen, setNavOpen] = useState(false); useEffect(() => { if (!loading && !user) { @@ -31,45 +51,71 @@ export default function DashboardLayout({ children }: { children: React.ReactNod ); } + const go = (href: string) => (e: React.MouseEvent) => { + e.preventDefault(); + setNavOpen(false); + router.push(href); + }; + return ( -
- {/* Top nav bar */} -
-
-
- - Tracker - - -
-
+ + + setNavOpen(o => !o)} /> + setNavOpen(false)} /> + + +
+ + Tracker + + + + {NAV_ITEMS.map(item => ( + + {item.label} + + ))} + + +
- {user.email} - + +
{user.email}
+ +
-
+ - {/* Page content */} -
+ {children} -
-
+ + ); } diff --git a/dashboards/tracker-web/src/components/ui/Primitives.tsx b/dashboards/tracker-web/src/components/ui/Primitives.tsx index 6a5db0f6..0f02a07c 100644 --- a/dashboards/tracker-web/src/components/ui/Primitives.tsx +++ b/dashboards/tracker-web/src/components/ui/Primitives.tsx @@ -146,3 +146,25 @@ export { } from '@bytelyst/ui'; export { Timeline, type TimelineItem, type TimelineProps } from '@bytelyst/ui'; + +// ── UX-8: AppShell nav shell ────────────────────────────────────────────── +export { + AppShell, + AppShellMain, + AppShellMobileToggle, + AppShellNav, + AppShellNavItem, + AppShellOverlay, + AppShellPageHeader, + AppShellSidebar, + AppShellSkipLink, + type AppShellMainProps, + type AppShellMobileToggleProps, + type AppShellNavItemProps, + type AppShellNavProps, + type AppShellOverlayProps, + type AppShellPageHeaderProps, + type AppShellProps, + type AppShellSidebarProps, + type AppShellSkipLinkProps, +} from '@bytelyst/ui';