| 1 | import { useEffect, useState, type ReactNode } from 'react';
|
| 2 | import { AppSidebar, type NavBadges, type ShellUser } from '@/components/app-sidebar';
|
| 3 | import { CommandPalette, CommandTrigger } from '@/components/command-palette';
|
| 4 | import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
|
| 5 | import type { Page } from '@/lib/navigation';
|
| 6 |
|
| 7 | export function AppShell({
|
| 8 | page,
|
| 9 | navigate,
|
| 10 | user,
|
| 11 | theme,
|
| 12 | onToggleTheme,
|
| 13 | onSignOut,
|
| 14 | badges,
|
| 15 | agents,
|
| 16 | attention,
|
| 17 | children,
|
| 18 | }: {
|
| 19 | page: Page;
|
| 20 | navigate: (page: Page) => void;
|
| 21 | user: ShellUser;
|
| 22 | theme: 'dark' | 'light';
|
| 23 | onToggleTheme: () => void;
|
| 24 | onSignOut: () => void;
|
| 25 | badges: NavBadges;
|
| 26 | agents: { agentId: string; name?: string }[];
|
| 27 | attention: { setup: number; invites: number; inbox: number };
|
| 28 | children: ReactNode;
|
| 29 | }) {
|
| 30 | const [commandOpen, setCommandOpen] = useState(false);
|
| 31 |
|
| 32 | useEffect(() => {
|
| 33 | setCommandOpen(false);
|
| 34 | }, [page]);
|
| 35 |
|
| 36 | useEffect(() => {
|
| 37 | const onKeyDown = (event: KeyboardEvent) => {
|
| 38 | if (event.key.toLowerCase() !== 'k' || !(event.metaKey || event.ctrlKey)) return;
|
| 39 | event.preventDefault();
|
| 40 | setCommandOpen((open) => !open);
|
| 41 | };
|
| 42 | window.addEventListener('keydown', onKeyDown);
|
| 43 | return () => window.removeEventListener('keydown', onKeyDown);
|
| 44 | }, []);
|
| 45 |
|
| 46 | return (
|
| 47 | <SidebarProvider className="min-h-svh">
|
| 48 | <a className="skipLink" href="#main">
|
| 49 | Skip to content
|
| 50 | </a>
|
| 51 | <AppSidebar
|
| 52 | page={page}
|
| 53 | navigate={navigate}
|
| 54 | user={user}
|
| 55 | theme={theme}
|
| 56 | onToggleTheme={onToggleTheme}
|
| 57 | onSignOut={onSignOut}
|
| 58 | badges={badges}
|
| 59 | />
|
| 60 | <SidebarInset id="main" className="appInset">
|
| 61 | <header className="appTopbar">
|
| 62 | <SidebarTrigger className="text-foreground" />
|
| 63 | <CommandTrigger onOpen={() => setCommandOpen(true)} />
|
| 64 | </header>
|
| 65 | <div className="appMain">{children}</div>
|
| 66 | </SidebarInset>
|
| 67 | <CommandPalette
|
| 68 | open={commandOpen}
|
| 69 | onOpenChange={setCommandOpen}
|
| 70 | navigate={navigate}
|
| 71 | theme={theme}
|
| 72 | onToggleTheme={onToggleTheme}
|
| 73 | onSignOut={onSignOut}
|
| 74 | agents={agents}
|
| 75 | attention={attention}
|
| 76 | />
|
| 77 | </SidebarProvider>
|
| 78 | );
|
| 79 | }
|