@agent-native/core 0.178.1 → 0.178.2-nightly-20260910195009
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +108 -121
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +87 -220
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +83 -221
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +324 -460
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +57 -247
- package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -48
- package/corpus/templates/clips/changelog/2026-09-10-open-mcp-connections-in-new-tabs.md +1 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +84 -94
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +1 -1
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +108 -296
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -212
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +72 -260
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +143 -362
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +64 -159
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +152 -165
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +82 -207
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +61 -234
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +73 -225
- package/dist/automation/index.d.ts +1 -1
- package/dist/client/EnvironmentBadge.d.ts +7 -4
- package/dist/client/EnvironmentBadge.js +26 -18
- package/dist/client/FeedbackButton.js +23 -8
- package/dist/client/app-providers.js +1 -1
- package/dist/client/auth/AuthPage.js +0 -38
- package/dist/client/components/icons/AgentNativeIcon.js +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/client/ui/AppSidebar.d.ts +15 -0
- package/dist/client/ui/AppSidebar.js +34 -0
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +19 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/beta-opt-out-html.js +2 -2
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +57 -247
- package/dist/vite/client.js +4 -1
- package/docs/content/template-clips-anonymous-intake.mdx +7 -5
- package/docs/content/template-clips-developers.mdx +1 -1
- package/package.json +3 -3
- package/src/templates/chat/app/components/layout/Sidebar.tsx +57 -247
|
@@ -13,11 +13,13 @@ import { useT } from "@agent-native/core/client/i18n";
|
|
|
13
13
|
import { openCommandMenu } from "@agent-native/core/client/navigation";
|
|
14
14
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
15
15
|
import {
|
|
16
|
+
AppSidebar,
|
|
17
|
+
AppSidebarNavItem,
|
|
16
18
|
AgentNativeIcon,
|
|
17
19
|
buildSignInReturnHref,
|
|
18
20
|
FeedbackButton,
|
|
21
|
+
type AppSidebarItemDefinition,
|
|
19
22
|
} from "@agent-native/core/client/ui";
|
|
20
|
-
import { SidebarFooterActions } from "@agent-native/toolkit/app-shell";
|
|
21
23
|
import {
|
|
22
24
|
ChatHistoryRail,
|
|
23
25
|
type ChatHistoryItem,
|
|
@@ -25,13 +27,10 @@ import {
|
|
|
25
27
|
import {
|
|
26
28
|
IconClipboardCheck,
|
|
27
29
|
IconEdit,
|
|
28
|
-
IconLayoutSidebarLeftCollapse,
|
|
29
|
-
IconLayoutSidebarLeftExpand,
|
|
30
30
|
IconMessageCircle,
|
|
31
31
|
IconPlus,
|
|
32
32
|
IconRefresh,
|
|
33
33
|
IconSettings,
|
|
34
|
-
IconSearch,
|
|
35
34
|
} from "@tabler/icons-react";
|
|
36
35
|
import { useEffect, useMemo, useState, type MouseEvent } from "react";
|
|
37
36
|
import { Link, useLocation, useNavigate } from "react-router";
|
|
@@ -540,216 +539,92 @@ export function Sidebar({
|
|
|
540
539
|
const { session, isLoading: sessionLoading } = useSession();
|
|
541
540
|
const t = useT();
|
|
542
541
|
const returnPath = planReturnPathFromLocation(location);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
className="size-8 shrink-0 text-muted-foreground"
|
|
554
|
-
onClick={() => onCollapsedChange?.(!collapsed)}
|
|
555
|
-
aria-label={
|
|
556
|
-
collapsed
|
|
557
|
-
? t("sidebar.expandSidebar")
|
|
558
|
-
: t("sidebar.collapseSidebar")
|
|
559
|
-
}
|
|
560
|
-
>
|
|
561
|
-
<ToggleIcon className="size-4" />
|
|
562
|
-
</Button>
|
|
563
|
-
</TooltipTrigger>
|
|
564
|
-
<TooltipContent side="right">
|
|
565
|
-
{collapsed ? t("sidebar.expandSidebar") : t("sidebar.collapseSidebar")}
|
|
566
|
-
</TooltipContent>
|
|
567
|
-
</Tooltip>
|
|
568
|
-
) : null;
|
|
569
|
-
const searchButton = (
|
|
570
|
-
<Tooltip>
|
|
571
|
-
<TooltipTrigger asChild>
|
|
572
|
-
<Button
|
|
573
|
-
type="button"
|
|
574
|
-
size="icon"
|
|
575
|
-
variant="ghost"
|
|
576
|
-
className="size-8 shrink-0 text-muted-foreground"
|
|
577
|
-
onClick={openCommandMenu}
|
|
578
|
-
aria-label={t("plansPage.overview.searchPlaceholder")}
|
|
579
|
-
>
|
|
580
|
-
<IconSearch className="size-4" />
|
|
581
|
-
</Button>
|
|
582
|
-
</TooltipTrigger>
|
|
583
|
-
<TooltipContent side="right">
|
|
584
|
-
{t("plansPage.overview.searchPlaceholder")}
|
|
585
|
-
</TooltipContent>
|
|
586
|
-
</Tooltip>
|
|
587
|
-
);
|
|
542
|
+
|
|
543
|
+
const secondaryItems: AppSidebarItemDefinition[] = [
|
|
544
|
+
{
|
|
545
|
+
to: "/settings",
|
|
546
|
+
label: t("navigation.settings"),
|
|
547
|
+
icon: IconSettings,
|
|
548
|
+
active: pathname.startsWith("/settings"),
|
|
549
|
+
},
|
|
550
|
+
];
|
|
551
|
+
|
|
588
552
|
const feedbackButton = (
|
|
589
|
-
<FeedbackButton
|
|
590
|
-
variant={collapsed ? "icon" : "sidebar"}
|
|
591
|
-
side="right"
|
|
592
|
-
className={collapsed ? "size-8" : "min-w-0"}
|
|
593
|
-
/>
|
|
553
|
+
<FeedbackButton variant={collapsed ? "icon" : "sidebar"} side="right" />
|
|
594
554
|
);
|
|
595
555
|
|
|
596
|
-
|
|
597
|
-
<
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
556
|
+
const orgSwitcher = session ? (
|
|
557
|
+
<OrgSwitcher compact={collapsed} />
|
|
558
|
+
) : !sessionLoading ? (
|
|
559
|
+
<Button
|
|
560
|
+
type="button"
|
|
561
|
+
size="sm"
|
|
562
|
+
variant="outline"
|
|
563
|
+
className={collapsed ? "!size-9 !p-0 text-xs" : "h-8 w-full px-3 text-xs"}
|
|
564
|
+
onClick={() => signInWithReturnPath(returnPath)}
|
|
603
565
|
>
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
collapsed ? "justify-center px-0" : "gap-2 px-3",
|
|
608
|
-
)}
|
|
609
|
-
>
|
|
610
|
-
<button
|
|
611
|
-
type="button"
|
|
612
|
-
onClick={() => onCollapsedChange?.(!collapsed)}
|
|
613
|
-
className={cn(
|
|
614
|
-
"flex min-w-0 items-center gap-2 rounded outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
615
|
-
collapsed ? "justify-center" : "flex-1 text-start",
|
|
616
|
-
)}
|
|
617
|
-
aria-label={
|
|
618
|
-
collapsible
|
|
619
|
-
? collapsed
|
|
620
|
-
? t("sidebar.expandSidebar")
|
|
621
|
-
: t("sidebar.collapseSidebar")
|
|
622
|
-
: undefined
|
|
623
|
-
}
|
|
624
|
-
disabled={!collapsible || !onCollapsedChange}
|
|
625
|
-
data-sidebar-brand-toggle
|
|
626
|
-
>
|
|
627
|
-
<AgentNativeIcon
|
|
628
|
-
aria-hidden="true"
|
|
629
|
-
className="h-3.5 w-6 shrink-0 text-sidebar-foreground"
|
|
630
|
-
/>
|
|
631
|
-
{!collapsed && (
|
|
632
|
-
<span className="truncate text-sm font-semibold tracking-tight">
|
|
633
|
-
{APP_TITLE}
|
|
634
|
-
</span>
|
|
635
|
-
)}
|
|
636
|
-
</button>
|
|
637
|
-
{!collapsed && <BrandingCustomizePopover />}
|
|
638
|
-
</div>
|
|
639
|
-
|
|
640
|
-
<nav className="flex-1 space-y-1 overflow-y-auto px-2 py-2">
|
|
641
|
-
{navItems.map((item) => {
|
|
642
|
-
const Icon = item.icon;
|
|
643
|
-
const isActive =
|
|
644
|
-
item.href === "/chat"
|
|
645
|
-
? pathname === "/chat"
|
|
646
|
-
: item.href === "/plans"
|
|
647
|
-
? pathname.startsWith("/plans") ||
|
|
648
|
-
pathname.startsWith("/recaps") ||
|
|
649
|
-
pathname.startsWith("/local-plans")
|
|
650
|
-
: pathname.startsWith(item.href);
|
|
651
|
-
const link = (
|
|
652
|
-
<Link
|
|
653
|
-
to={item.href}
|
|
654
|
-
className={cn(
|
|
655
|
-
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors",
|
|
656
|
-
isActive
|
|
657
|
-
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
658
|
-
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
659
|
-
collapsed && "justify-center gap-0 px-0",
|
|
660
|
-
)}
|
|
661
|
-
>
|
|
662
|
-
<Icon className="h-4 w-4 shrink-0" />
|
|
663
|
-
{collapsed ? (
|
|
664
|
-
<span className="sr-only">{t(item.labelKey)}</span>
|
|
665
|
-
) : (
|
|
666
|
-
t(item.labelKey)
|
|
667
|
-
)}
|
|
668
|
-
</Link>
|
|
669
|
-
);
|
|
670
|
-
return (
|
|
671
|
-
<div key={item.href}>
|
|
672
|
-
{link}
|
|
673
|
-
{item.href === "/chat" ? (
|
|
674
|
-
<PlanChatsSection collapsed={collapsed} open={isActive} />
|
|
675
|
-
) : null}
|
|
676
|
-
{item.href === "/plans" && isActive ? (
|
|
677
|
-
<PlansSidebarSection collapsed={collapsed} />
|
|
678
|
-
) : null}
|
|
679
|
-
</div>
|
|
680
|
-
);
|
|
681
|
-
})}
|
|
682
|
-
</nav>
|
|
683
|
-
|
|
684
|
-
<nav className="grid shrink-0 gap-1 px-2 py-1">
|
|
685
|
-
{bottomNavItems.map((item) => {
|
|
686
|
-
const Icon = item.icon;
|
|
687
|
-
const isActive = pathname.startsWith(item.href);
|
|
688
|
-
const link = (
|
|
689
|
-
<Link
|
|
690
|
-
to={item.href}
|
|
691
|
-
className={cn(
|
|
692
|
-
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors",
|
|
693
|
-
isActive
|
|
694
|
-
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
695
|
-
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
696
|
-
collapsed && "justify-center gap-0 px-0",
|
|
697
|
-
)}
|
|
698
|
-
aria-label={collapsed ? t(item.labelKey) : undefined}
|
|
699
|
-
>
|
|
700
|
-
<Icon className="h-4 w-4 shrink-0" />
|
|
701
|
-
{collapsed ? (
|
|
702
|
-
<span className="sr-only">{t(item.labelKey)}</span>
|
|
703
|
-
) : (
|
|
704
|
-
t(item.labelKey)
|
|
705
|
-
)}
|
|
706
|
-
</Link>
|
|
707
|
-
);
|
|
708
|
-
return collapsed ? (
|
|
709
|
-
<Tooltip key={item.href}>
|
|
710
|
-
<TooltipTrigger asChild>{link}</TooltipTrigger>
|
|
711
|
-
<TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
|
|
712
|
-
</Tooltip>
|
|
713
|
-
) : (
|
|
714
|
-
<div key={item.href}>{link}</div>
|
|
715
|
-
);
|
|
716
|
-
})}
|
|
717
|
-
</nav>
|
|
718
|
-
|
|
719
|
-
{!collapsed && session ? (
|
|
720
|
-
<div className="space-y-2 px-3 py-2 empty:hidden">
|
|
721
|
-
<DevDatabaseLink />
|
|
722
|
-
<OrgSwitcher />
|
|
723
|
-
</div>
|
|
724
|
-
) : null}
|
|
566
|
+
{collapsed ? "In" : t("sidebar.signIn")}
|
|
567
|
+
</Button>
|
|
568
|
+
) : null;
|
|
725
569
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
570
|
+
return (
|
|
571
|
+
<AppSidebar
|
|
572
|
+
collapsed={collapsed}
|
|
573
|
+
collapsible={collapsible}
|
|
574
|
+
onCollapsedChange={onCollapsedChange}
|
|
575
|
+
brandName={APP_TITLE}
|
|
576
|
+
brandHref="/plans"
|
|
577
|
+
brandLink={
|
|
578
|
+
<div className="group/brand flex min-w-0 items-center gap-1">
|
|
579
|
+
<Link
|
|
580
|
+
to="/plans"
|
|
581
|
+
className="flex min-w-0 items-center gap-2 rounded text-start outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
735
582
|
>
|
|
736
|
-
|
|
737
|
-
|
|
583
|
+
<AgentNativeIcon
|
|
584
|
+
aria-hidden="true"
|
|
585
|
+
className="h-3.5 w-6 shrink-0 text-primary"
|
|
586
|
+
/>
|
|
587
|
+
{!collapsed && (
|
|
588
|
+
<span className="truncate text-sm font-semibold text-primary">
|
|
589
|
+
{APP_TITLE}
|
|
590
|
+
</span>
|
|
591
|
+
)}
|
|
592
|
+
</Link>
|
|
593
|
+
{!collapsed ? <BrandingCustomizePopover /> : null}
|
|
738
594
|
</div>
|
|
739
|
-
|
|
595
|
+
}
|
|
596
|
+
secondaryItems={secondaryItems}
|
|
597
|
+
feedback={feedbackButton}
|
|
598
|
+
orgSwitcher={orgSwitcher}
|
|
599
|
+
footerExtras={<DevDatabaseLink />}
|
|
600
|
+
>
|
|
601
|
+
<div>
|
|
602
|
+
<AppSidebarNavItem
|
|
603
|
+
to="/chat"
|
|
604
|
+
label={t("navigation.ask")}
|
|
605
|
+
icon={IconMessageCircle}
|
|
606
|
+
active={pathname === "/chat"}
|
|
607
|
+
/>
|
|
608
|
+
<PlanChatsSection collapsed={collapsed} open={pathname === "/chat"} />
|
|
609
|
+
</div>
|
|
740
610
|
|
|
741
|
-
|
|
742
|
-
<
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
611
|
+
<div>
|
|
612
|
+
<AppSidebarNavItem
|
|
613
|
+
to="/plans"
|
|
614
|
+
label={t("navigation.plan")}
|
|
615
|
+
icon={IconClipboardCheck}
|
|
616
|
+
active={
|
|
617
|
+
pathname.startsWith("/plans") ||
|
|
618
|
+
pathname.startsWith("/recaps") ||
|
|
619
|
+
pathname.startsWith("/local-plans")
|
|
620
|
+
}
|
|
621
|
+
/>
|
|
622
|
+
{pathname.startsWith("/plans") ||
|
|
623
|
+
pathname.startsWith("/recaps") ||
|
|
624
|
+
pathname.startsWith("/local-plans") ? (
|
|
625
|
+
<PlansSidebarSection collapsed={collapsed} />
|
|
626
|
+
) : null}
|
|
627
|
+
</div>
|
|
628
|
+
</AppSidebar>
|
|
754
629
|
);
|
|
755
630
|
}
|
|
@@ -2,42 +2,28 @@ import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
|
2
2
|
import { useT } from "@agent-native/core/client/i18n";
|
|
3
3
|
import { openCommandMenu } from "@agent-native/core/client/navigation";
|
|
4
4
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
AppSidebar,
|
|
7
|
+
FeedbackButton,
|
|
8
|
+
type AppSidebarItemDefinition,
|
|
9
|
+
} from "@agent-native/core/client/ui";
|
|
7
10
|
import {
|
|
8
11
|
IconLayoutGrid,
|
|
9
12
|
IconComponents,
|
|
10
|
-
IconSettings,
|
|
11
|
-
IconLayoutSidebarLeftCollapse,
|
|
12
|
-
IconLayoutSidebarLeftExpand,
|
|
13
13
|
IconSearch,
|
|
14
|
+
IconSettings,
|
|
14
15
|
} from "@tabler/icons-react";
|
|
15
|
-
import {
|
|
16
|
+
import { useLocation } from "react-router";
|
|
16
17
|
|
|
18
|
+
import { Button } from "@/components/ui/button";
|
|
17
19
|
import {
|
|
18
20
|
Tooltip,
|
|
19
21
|
TooltipContent,
|
|
20
22
|
TooltipTrigger,
|
|
21
23
|
} from "@/components/ui/tooltip";
|
|
22
|
-
import { cn } from "@/lib/utils";
|
|
23
|
-
|
|
24
|
-
const navItems = [
|
|
25
|
-
{ icon: IconLayoutGrid, labelKey: "navigation.decks", href: "/home" },
|
|
26
|
-
{
|
|
27
|
-
icon: IconComponents,
|
|
28
|
-
labelKey: "navigation.designSystems",
|
|
29
|
-
href: "/design-systems",
|
|
30
|
-
},
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
const bottomNavItems = [
|
|
34
|
-
{ icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
|
|
35
|
-
];
|
|
36
24
|
|
|
37
25
|
interface SidebarProps {
|
|
38
26
|
collapsed: boolean;
|
|
39
|
-
/** Omit to hide the collapse/expand toggle (e.g. inside the mobile drawer,
|
|
40
|
-
* where toggling the desktop preference is meaningless). */
|
|
41
27
|
onToggleCollapsed?: () => void;
|
|
42
28
|
}
|
|
43
29
|
|
|
@@ -50,230 +36,71 @@ export function Sidebar({ collapsed, onToggleCollapsed }: SidebarProps) {
|
|
|
50
36
|
? location.pathname === "/home"
|
|
51
37
|
: location.pathname.startsWith(href);
|
|
52
38
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
39
|
+
const items: AppSidebarItemDefinition[] = [
|
|
40
|
+
{
|
|
41
|
+
to: "/home",
|
|
42
|
+
label: t("navigation.decks"),
|
|
43
|
+
icon: IconLayoutGrid,
|
|
44
|
+
active: isItemActive("/home"),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
to: "/design-systems",
|
|
48
|
+
label: t("navigation.designSystems"),
|
|
49
|
+
icon: IconComponents,
|
|
50
|
+
active: isItemActive("/design-systems"),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const secondaryItems: AppSidebarItemDefinition[] = [
|
|
55
|
+
{
|
|
56
|
+
to: "/settings",
|
|
57
|
+
label: t("navigation.settings"),
|
|
58
|
+
icon: IconSettings,
|
|
59
|
+
active: isItemActive("/settings"),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const feedbackButton = (
|
|
64
|
+
<FeedbackButton variant={collapsed ? "icon" : "sidebar"} side="right" />
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const orgSwitcher = <OrgSwitcher compact={collapsed} />;
|
|
68
|
+
|
|
78
69
|
const searchButton = (
|
|
79
70
|
<Tooltip>
|
|
80
71
|
<TooltipTrigger asChild>
|
|
81
|
-
<
|
|
72
|
+
<Button
|
|
82
73
|
type="button"
|
|
74
|
+
variant="ghost"
|
|
75
|
+
size="icon"
|
|
76
|
+
className="size-9 shrink-0 text-primary hover:bg-accent/60 hover:text-primary"
|
|
83
77
|
onClick={openCommandMenu}
|
|
84
78
|
aria-label={t("root.searchDecks")}
|
|
85
|
-
className="flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground"
|
|
86
79
|
>
|
|
87
|
-
<IconSearch className="
|
|
88
|
-
</
|
|
80
|
+
<IconSearch className="size-4" />
|
|
81
|
+
</Button>
|
|
89
82
|
</TooltipTrigger>
|
|
90
83
|
<TooltipContent side="right">{t("root.searchDecks")}</TooltipContent>
|
|
91
84
|
</Tooltip>
|
|
92
85
|
);
|
|
93
|
-
const feedbackButton = (
|
|
94
|
-
<FeedbackButton
|
|
95
|
-
variant={collapsed ? "icon" : "sidebar"}
|
|
96
|
-
side="right"
|
|
97
|
-
className={collapsed ? "size-8" : "min-w-0"}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const brand = (
|
|
102
|
-
<div
|
|
103
|
-
className={cn(
|
|
104
|
-
"flex items-center gap-2",
|
|
105
|
-
collapsed ? "size-8 justify-center" : "min-w-0 flex-1",
|
|
106
|
-
)}
|
|
107
|
-
>
|
|
108
|
-
<AgentNativeIcon
|
|
109
|
-
aria-hidden="true"
|
|
110
|
-
className="h-3.5 w-6 shrink-0 text-sidebar-foreground"
|
|
111
|
-
/>
|
|
112
|
-
{!collapsed && (
|
|
113
|
-
<span className="truncate text-sm font-semibold tracking-tight">
|
|
114
|
-
{t("navigation.brand")}
|
|
115
|
-
</span>
|
|
116
|
-
)}
|
|
117
|
-
</div>
|
|
118
|
-
);
|
|
119
|
-
const brandControl = onToggleCollapsed ? (
|
|
120
|
-
<Tooltip delayDuration={0}>
|
|
121
|
-
<TooltipTrigger asChild>
|
|
122
|
-
<button
|
|
123
|
-
type="button"
|
|
124
|
-
onClick={onToggleCollapsed}
|
|
125
|
-
aria-label={
|
|
126
|
-
collapsed
|
|
127
|
-
? t("sidebar.expandSidebar")
|
|
128
|
-
: t("sidebar.collapseSidebar")
|
|
129
|
-
}
|
|
130
|
-
className={cn(
|
|
131
|
-
"flex min-w-0 items-center rounded-md text-foreground outline-none transition-colors hover:bg-sidebar-accent/50 focus-visible:ring-2 focus-visible:ring-ring",
|
|
132
|
-
collapsed
|
|
133
|
-
? "size-8 justify-center"
|
|
134
|
-
: "w-full gap-2 px-1 py-1 text-start",
|
|
135
|
-
)}
|
|
136
|
-
data-sidebar-brand-toggle
|
|
137
|
-
>
|
|
138
|
-
{brand}
|
|
139
|
-
</button>
|
|
140
|
-
</TooltipTrigger>
|
|
141
|
-
<TooltipContent side="right">
|
|
142
|
-
{collapsed ? t("sidebar.expandSidebar") : t("sidebar.collapseSidebar")}
|
|
143
|
-
</TooltipContent>
|
|
144
|
-
</Tooltip>
|
|
145
|
-
) : (
|
|
146
|
-
brand
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
if (collapsed) {
|
|
150
|
-
return (
|
|
151
|
-
<aside className="flex h-full w-12 shrink-0 flex-col items-center overflow-hidden bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-out">
|
|
152
|
-
<div className="flex h-12 w-full shrink-0 items-center justify-center">
|
|
153
|
-
{brandControl}
|
|
154
|
-
</div>
|
|
155
|
-
<nav className="flex min-h-0 flex-1 flex-col items-center gap-1 overflow-y-auto pt-1">
|
|
156
|
-
{navItems.map((item) => {
|
|
157
|
-
const Icon = item.icon;
|
|
158
|
-
const isActive = isItemActive(item.href);
|
|
159
|
-
return (
|
|
160
|
-
<Tooltip key={item.href} delayDuration={0}>
|
|
161
|
-
<TooltipTrigger asChild>
|
|
162
|
-
<Link
|
|
163
|
-
to={item.href}
|
|
164
|
-
aria-label={t(item.labelKey)}
|
|
165
|
-
className={cn(
|
|
166
|
-
"flex h-10 w-10 items-center justify-center rounded-md transition-colors",
|
|
167
|
-
isActive
|
|
168
|
-
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
169
|
-
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
170
|
-
)}
|
|
171
|
-
>
|
|
172
|
-
<Icon className="h-4 w-4" />
|
|
173
|
-
</Link>
|
|
174
|
-
</TooltipTrigger>
|
|
175
|
-
<TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
|
|
176
|
-
</Tooltip>
|
|
177
|
-
);
|
|
178
|
-
})}
|
|
179
|
-
</nav>
|
|
180
|
-
<nav className="flex shrink-0 flex-col items-center gap-1 py-1">
|
|
181
|
-
{bottomNavItems.map((item) => {
|
|
182
|
-
const Icon = item.icon;
|
|
183
|
-
return (
|
|
184
|
-
<Tooltip key={item.href} delayDuration={0}>
|
|
185
|
-
<TooltipTrigger asChild>
|
|
186
|
-
<Link
|
|
187
|
-
to={item.href}
|
|
188
|
-
aria-label={t(item.labelKey)}
|
|
189
|
-
className={cn(
|
|
190
|
-
"flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
191
|
-
isItemActive(item.href) &&
|
|
192
|
-
"bg-sidebar-accent text-sidebar-accent-foreground",
|
|
193
|
-
)}
|
|
194
|
-
>
|
|
195
|
-
<Icon className="h-4 w-4 shrink-0" />
|
|
196
|
-
</Link>
|
|
197
|
-
</TooltipTrigger>
|
|
198
|
-
<TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
|
|
199
|
-
</Tooltip>
|
|
200
|
-
);
|
|
201
|
-
})}
|
|
202
|
-
</nav>
|
|
203
|
-
<SidebarFooterActions
|
|
204
|
-
collapsed
|
|
205
|
-
feedback={feedbackButton}
|
|
206
|
-
search={searchButton}
|
|
207
|
-
collapse={collapseButton}
|
|
208
|
-
/>
|
|
209
|
-
</aside>
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
86
|
|
|
213
87
|
return (
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
)}
|
|
232
|
-
>
|
|
233
|
-
<Icon className="h-4 w-4 shrink-0" />
|
|
234
|
-
{t(item.labelKey)}
|
|
235
|
-
</Link>
|
|
236
|
-
);
|
|
237
|
-
})}
|
|
238
|
-
</nav>
|
|
239
|
-
|
|
240
|
-
<div className="mt-auto shrink-0">
|
|
241
|
-
<nav className="space-y-1 px-2 py-1">
|
|
242
|
-
{bottomNavItems.map((item) => {
|
|
243
|
-
const Icon = item.icon;
|
|
244
|
-
const isActive = isItemActive(item.href);
|
|
245
|
-
return (
|
|
246
|
-
<Link
|
|
247
|
-
key={item.href}
|
|
248
|
-
to={item.href}
|
|
249
|
-
className={cn(
|
|
250
|
-
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm",
|
|
251
|
-
isActive
|
|
252
|
-
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
253
|
-
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
254
|
-
)}
|
|
255
|
-
>
|
|
256
|
-
<Icon className="h-4 w-4 shrink-0" />
|
|
257
|
-
{t(item.labelKey)}
|
|
258
|
-
</Link>
|
|
259
|
-
);
|
|
260
|
-
})}
|
|
261
|
-
</nav>
|
|
262
|
-
|
|
263
|
-
<div className="px-3 py-2 empty:hidden">
|
|
264
|
-
<OrgSwitcher />
|
|
265
|
-
</div>
|
|
266
|
-
|
|
267
|
-
<div className="px-3 py-2 empty:hidden">
|
|
268
|
-
<DevDatabaseLink />
|
|
269
|
-
</div>
|
|
270
|
-
<SidebarFooterActions
|
|
271
|
-
feedback={feedbackButton}
|
|
272
|
-
search={searchButton}
|
|
273
|
-
collapse={collapseButton}
|
|
274
|
-
/>
|
|
275
|
-
</div>
|
|
276
|
-
</div>
|
|
277
|
-
</aside>
|
|
88
|
+
<AppSidebar
|
|
89
|
+
collapsed={collapsed}
|
|
90
|
+
collapsible={Boolean(onToggleCollapsed)}
|
|
91
|
+
onCollapsedChange={onToggleCollapsed}
|
|
92
|
+
brandName={t("navigation.brand")}
|
|
93
|
+
brandHref="/home"
|
|
94
|
+
items={items}
|
|
95
|
+
secondaryItems={secondaryItems}
|
|
96
|
+
feedback={feedbackButton}
|
|
97
|
+
orgSwitcher={orgSwitcher}
|
|
98
|
+
footerExtras={
|
|
99
|
+
<>
|
|
100
|
+
{searchButton}
|
|
101
|
+
<DevDatabaseLink />
|
|
102
|
+
</>
|
|
103
|
+
}
|
|
104
|
+
/>
|
|
278
105
|
);
|
|
279
106
|
}
|