The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.

Viewing files at commit 874239cc591fCommit detailsView latest

apps/dashboard/src/components/app-shell.tsx 79 lines · 2.2 KB · tsx
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
}