@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.
Files changed (48) hide show
  1. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +108 -121
  2. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +87 -220
  3. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +83 -221
  4. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +324 -460
  5. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +57 -247
  6. package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -48
  7. package/corpus/templates/clips/changelog/2026-09-10-open-mcp-connections-in-new-tabs.md +1 -0
  8. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +84 -94
  9. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +1 -1
  10. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +108 -296
  11. package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -212
  12. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +72 -260
  13. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +143 -362
  14. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +64 -159
  15. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +152 -165
  16. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +82 -207
  17. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +61 -234
  18. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +73 -225
  19. package/dist/automation/index.d.ts +1 -1
  20. package/dist/client/EnvironmentBadge.d.ts +7 -4
  21. package/dist/client/EnvironmentBadge.js +26 -18
  22. package/dist/client/FeedbackButton.js +23 -8
  23. package/dist/client/app-providers.js +1 -1
  24. package/dist/client/auth/AuthPage.js +0 -38
  25. package/dist/client/components/icons/AgentNativeIcon.js +1 -1
  26. package/dist/client/index.d.ts +1 -0
  27. package/dist/client/index.js +1 -0
  28. package/dist/client/ui/AppSidebar.d.ts +15 -0
  29. package/dist/client/ui/AppSidebar.js +34 -0
  30. package/dist/client/ui/index.d.ts +1 -0
  31. package/dist/client/ui/index.js +1 -0
  32. package/dist/collab/awareness.d.ts +2 -2
  33. package/dist/collab/struct-routes.d.ts +1 -1
  34. package/dist/config.d.ts +4 -0
  35. package/dist/config.js +19 -3
  36. package/dist/progress/routes.d.ts +1 -1
  37. package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
  38. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  39. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  40. package/dist/resources/handlers.d.ts +1 -1
  41. package/dist/secrets/routes.d.ts +9 -9
  42. package/dist/server/beta-opt-out-html.js +2 -2
  43. package/dist/templates/chat/app/components/layout/Sidebar.tsx +57 -247
  44. package/dist/vite/client.js +4 -1
  45. package/docs/content/template-clips-anonymous-intake.mdx +7 -5
  46. package/docs/content/template-clips-developers.mdx +1 -1
  47. package/package.json +3 -3
  48. package/src/templates/chat/app/components/layout/Sidebar.tsx +57 -247
@@ -1,41 +1,19 @@
1
1
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
2
2
  import { useT } from "@agent-native/core/client/i18n";
3
- import { openCommandMenu } from "@agent-native/core/client/navigation";
4
3
  import { OrgSwitcher } from "@agent-native/core/client/org";
5
- import { AgentNativeIcon, FeedbackButton } from "@agent-native/core/client/ui";
6
- import { SidebarFooterActions } from "@agent-native/toolkit/app-shell";
7
4
  import {
8
- IconPencil,
9
- IconTemplate,
5
+ AppSidebar,
6
+ FeedbackButton,
7
+ type AppSidebarItemDefinition,
8
+ } from "@agent-native/core/client/ui";
9
+ import {
10
10
  IconComponents,
11
+ IconPencil,
11
12
  IconSettings,
12
- IconLayoutSidebarLeftCollapse,
13
- IconLayoutSidebarLeftExpand,
14
- IconSearch,
13
+ IconTemplate,
15
14
  } from "@tabler/icons-react";
16
15
  import { useEffect, useState } from "react";
17
- import { Link, useLocation } from "react-router";
18
-
19
- import {
20
- Tooltip,
21
- TooltipContent,
22
- TooltipTrigger,
23
- } from "@/components/ui/tooltip";
24
- import { cn } from "@/lib/utils";
25
-
26
- const navItems = [
27
- { icon: IconPencil, labelKey: "navigation.designs", href: "/home" },
28
- { icon: IconTemplate, labelKey: "navigation.templates", href: "/templates" },
29
- {
30
- icon: IconComponents,
31
- labelKey: "navigation.designSystems",
32
- href: "/design-systems",
33
- },
34
- ];
35
-
36
- const bottomNavItems = [
37
- { icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
38
- ];
16
+ import { useLocation } from "react-router";
39
17
 
40
18
  const COLLAPSE_KEY = "design.sidebar.collapsed";
41
19
 
@@ -60,191 +38,56 @@ export function Sidebar() {
60
38
  }
61
39
  }, [collapsed]);
62
40
 
63
- const collapseButton = (
64
- <Tooltip delayDuration={0}>
65
- <TooltipTrigger asChild>
66
- <button
67
- type="button"
68
- onClick={() => setCollapsed((value) => !value)}
69
- className="flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground"
70
- aria-label={
71
- collapsed
72
- ? t("navigation.expandSidebar")
73
- : t("navigation.collapseSidebar")
74
- }
75
- >
76
- {collapsed ? (
77
- <IconLayoutSidebarLeftExpand className="h-4 w-4 rtl:-scale-x-100" />
78
- ) : (
79
- <IconLayoutSidebarLeftCollapse className="h-4 w-4 rtl:-scale-x-100" />
80
- )}
81
- </button>
82
- </TooltipTrigger>
83
- <TooltipContent side="right">
84
- {collapsed
85
- ? t("navigation.expandSidebar")
86
- : t("navigation.collapseSidebar")}
87
- </TooltipContent>
88
- </Tooltip>
89
- );
90
- const searchButton = (
91
- <Tooltip delayDuration={0}>
92
- <TooltipTrigger asChild>
93
- <button
94
- type="button"
95
- onClick={openCommandMenu}
96
- className="flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground"
97
- aria-label={t("root.commandSearch")}
98
- >
99
- <IconSearch className="h-4 w-4" />
100
- </button>
101
- </TooltipTrigger>
102
- <TooltipContent side="right">{t("root.commandSearch")}</TooltipContent>
103
- </Tooltip>
104
- );
105
- const feedbackButton = (
106
- <FeedbackButton
107
- variant={collapsed ? "icon" : "sidebar"}
108
- side="right"
109
- className={collapsed ? "h-8 w-8" : "min-w-0"}
110
- />
111
- );
41
+ const items: AppSidebarItemDefinition[] = [
42
+ {
43
+ to: "/home",
44
+ label: t("navigation.designs"),
45
+ icon: IconPencil,
46
+ active:
47
+ location.pathname === "/home" ||
48
+ location.pathname.startsWith("/design/") ||
49
+ location.pathname.startsWith("/d/"),
50
+ },
51
+ {
52
+ to: "/templates",
53
+ label: t("navigation.templates"),
54
+ icon: IconTemplate,
55
+ active: location.pathname.startsWith("/templates"),
56
+ },
57
+ {
58
+ to: "/design-systems",
59
+ label: t("navigation.designSystems"),
60
+ icon: IconComponents,
61
+ active: location.pathname.startsWith("/design-systems"),
62
+ },
63
+ ];
112
64
 
113
- return (
114
- <aside
115
- className={cn(
116
- "flex h-full min-w-0 shrink-0 flex-col overflow-hidden bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-out",
117
- collapsed ? "w-14" : "w-56",
118
- )}
119
- >
120
- <div
121
- className={cn(
122
- "flex h-12 shrink-0 items-center border-b border-border",
123
- collapsed ? "justify-center px-2" : "justify-between px-4",
124
- )}
125
- >
126
- <button
127
- type="button"
128
- onClick={() => setCollapsed((value) => !value)}
129
- aria-label={
130
- collapsed
131
- ? t("navigation.expandSidebar")
132
- : t("navigation.collapseSidebar")
133
- }
134
- className={cn(
135
- "flex items-center gap-2 rounded outline-none focus-visible:ring-2 focus-visible:ring-ring",
136
- collapsed ? "size-8 justify-center" : "text-start",
137
- )}
138
- data-sidebar-brand-toggle
139
- >
140
- <AgentNativeIcon
141
- aria-hidden="true"
142
- className="h-3.5 w-6 shrink-0 text-sidebar-foreground"
143
- />
144
- {!collapsed && (
145
- <span className="text-sm font-semibold tracking-tight">
146
- {t("navigation.brand")}
147
- </span>
148
- )}
149
- </button>
150
- </div>
65
+ const secondaryItems: AppSidebarItemDefinition[] = [
66
+ {
67
+ to: "/settings",
68
+ label: t("navigation.settings"),
69
+ icon: IconSettings,
70
+ active: location.pathname.startsWith("/settings"),
71
+ },
72
+ ];
151
73
 
152
- <div className="flex min-h-0 flex-1 flex-col overflow-y-auto">
153
- <nav className={cn("space-y-1 py-2", collapsed ? "px-1.5" : "px-2")}>
154
- {navItems.map((item) => {
155
- const Icon = item.icon;
156
- const isActive =
157
- item.href === "/home"
158
- ? location.pathname === "/home" ||
159
- location.pathname.startsWith("/design/")
160
- : location.pathname.startsWith(item.href);
161
- const link = (
162
- <Link
163
- key={item.href}
164
- to={item.href}
165
- className={cn(
166
- "flex items-center rounded-lg text-sm",
167
- collapsed ? "h-9 w-9 justify-center" : "gap-3 px-3 py-2",
168
- isActive
169
- ? "bg-sidebar-accent text-sidebar-accent-foreground"
170
- : "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
171
- )}
172
- >
173
- <Icon className="h-4 w-4 shrink-0" />
174
- {!collapsed && t(item.labelKey)}
175
- </Link>
176
- );
177
- if (collapsed) {
178
- return (
179
- <Tooltip key={item.href} delayDuration={0}>
180
- <TooltipTrigger asChild>{link}</TooltipTrigger>
181
- <TooltipContent side="right">
182
- {t(item.labelKey)}
183
- </TooltipContent>
184
- </Tooltip>
185
- );
186
- }
187
- return link;
188
- })}
189
- </nav>
74
+ const feedbackButton = (
75
+ <FeedbackButton variant={collapsed ? "icon" : "sidebar"} side="right" />
76
+ );
190
77
 
191
- <div className="mt-auto shrink-0">
192
- <nav
193
- className={cn(
194
- "grid gap-1",
195
- collapsed ? "justify-items-center px-1.5 py-1" : "px-2 py-1",
196
- )}
197
- >
198
- {bottomNavItems.map((item) => {
199
- const Icon = item.icon;
200
- const isActive = location.pathname.startsWith(item.href);
201
- const link = (
202
- <Link
203
- to={item.href}
204
- className={cn(
205
- "flex items-center rounded-lg text-sm",
206
- collapsed ? "h-9 w-9 justify-center" : "gap-3 px-3 py-2",
207
- isActive
208
- ? "bg-sidebar-accent text-sidebar-accent-foreground"
209
- : "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
210
- )}
211
- aria-label={collapsed ? t(item.labelKey) : undefined}
212
- >
213
- <Icon className="h-4 w-4 shrink-0" />
214
- {!collapsed && t(item.labelKey)}
215
- </Link>
216
- );
217
- return collapsed ? (
218
- <Tooltip key={item.href} delayDuration={0}>
219
- <TooltipTrigger asChild>{link}</TooltipTrigger>
220
- <TooltipContent side="right">
221
- {t(item.labelKey)}
222
- </TooltipContent>
223
- </Tooltip>
224
- ) : (
225
- <div key={item.href}>{link}</div>
226
- );
227
- })}
228
- </nav>
78
+ const orgSwitcher = <OrgSwitcher compact={collapsed} />;
229
79
 
230
- {!collapsed && (
231
- <div className="mt-auto shrink-0">
232
- <div className="px-3 py-2 empty:hidden">
233
- <OrgSwitcher reserveSpace />
234
- </div>
235
- <div className="px-3 py-2 empty:hidden">
236
- <DevDatabaseLink />
237
- </div>
238
- </div>
239
- )}
240
- </div>
241
- <SidebarFooterActions
242
- collapsed={collapsed}
243
- feedback={feedbackButton}
244
- search={searchButton}
245
- collapse={collapseButton}
246
- />
247
- </div>
248
- </aside>
80
+ return (
81
+ <AppSidebar
82
+ collapsed={collapsed}
83
+ onCollapsedChange={setCollapsed}
84
+ brandName={t("navigation.brand")}
85
+ brandHref="/home"
86
+ items={items}
87
+ secondaryItems={secondaryItems}
88
+ feedback={feedbackButton}
89
+ orgSwitcher={orgSwitcher}
90
+ footerExtras={<DevDatabaseLink />}
91
+ />
249
92
  );
250
93
  }
@@ -6,15 +6,17 @@ import {
6
6
  import { useT } from "@agent-native/core/client/i18n";
7
7
  import { openCommandMenu } from "@agent-native/core/client/navigation";
8
8
  import { OrgSwitcher } from "@agent-native/core/client/org";
9
- import { AgentNativeIcon, FeedbackButton } from "@agent-native/core/client/ui";
10
- import { SidebarFooterActions } from "@agent-native/toolkit/app-shell";
9
+ import {
10
+ AppSidebar,
11
+ AppSidebarNavItem,
12
+ FeedbackButton,
13
+ type AppSidebarItemDefinition,
14
+ } from "@agent-native/core/client/ui";
11
15
  import {
12
16
  ChatHistoryRail,
13
17
  type ChatHistoryItem,
14
18
  } from "@agent-native/toolkit/chat-history";
15
19
  import {
16
- IconLayoutSidebarLeftCollapse,
17
- IconLayoutSidebarLeftExpand,
18
20
  IconGitPullRequest,
19
21
  IconHierarchy2,
20
22
  IconMessageCircle,
@@ -22,46 +24,16 @@ import {
22
24
  IconSettings,
23
25
  } from "@tabler/icons-react";
24
26
  import { useEffect, useMemo } from "react";
25
- import { Link, useLocation, useNavigate } from "react-router";
27
+ import { useLocation, useNavigate } from "react-router";
26
28
  import { toast } from "sonner";
27
29
 
30
+ import { Button } from "@/components/ui/button";
28
31
  import {
29
32
  Tooltip,
30
33
  TooltipContent,
31
34
  TooltipTrigger,
32
35
  } from "@/components/ui/tooltip";
33
36
  import { APP_TITLE } from "@/lib/app-config";
34
- import { cn } from "@/lib/utils";
35
-
36
- const navItems = [
37
- {
38
- icon: IconMessageCircle,
39
- labelKey: "navigation.chat",
40
- href: "/chat",
41
- view: "chat",
42
- },
43
- {
44
- icon: IconGitPullRequest,
45
- labelKey: "navigation.triage",
46
- href: "/factory",
47
- view: "factory",
48
- },
49
- {
50
- icon: IconHierarchy2,
51
- labelKey: "navigation.agents",
52
- href: "/agents",
53
- view: "agents",
54
- },
55
- ];
56
-
57
- const bottomNavItems = [
58
- {
59
- icon: IconSettings,
60
- labelKey: "navigation.settings",
61
- href: "/settings",
62
- view: "settings",
63
- },
64
- ];
65
37
 
66
38
  const CHAT_STORAGE_KEY = "chat";
67
39
  const CHAT_ACTIVE_THREAD_KEY = `agent-chat-active-thread:${CHAT_STORAGE_KEY}`;
@@ -292,248 +264,88 @@ export function Sidebar({
292
264
  const t = useT();
293
265
  const isChatRoute =
294
266
  location.pathname === "/chat" || location.pathname.startsWith("/chat/");
295
- const ToggleIcon = collapsed
296
- ? IconLayoutSidebarLeftExpand
297
- : IconLayoutSidebarLeftCollapse;
298
- const navClass = ({ isActive }: { isActive: boolean }) =>
299
- cn(
300
- "flex items-center text-sm transition-colors",
301
- collapsed
302
- ? "relative h-10 w-full justify-center rounded-none px-0"
303
- : "h-9 rounded-md gap-3 px-3",
304
- isActive
305
- ? collapsed
306
- ? "bg-sidebar-accent text-sidebar-accent-foreground"
307
- : "bg-sidebar-accent text-sidebar-accent-foreground"
308
- : collapsed
309
- ? "text-sidebar-foreground/70 hover:bg-sidebar-accent/55 hover:text-sidebar-accent-foreground"
310
- : "text-sidebar-foreground hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground",
311
- );
312
- const collapseButton = collapsible ? (
313
- <Tooltip>
314
- <TooltipTrigger asChild>
315
- <button
316
- type="button"
317
- onClick={() => onCollapsedChange?.(!collapsed)}
318
- className={cn(
319
- "flex shrink-0 items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
320
- collapsed ? "size-8" : "size-7",
321
- )}
322
- aria-label={
323
- collapsed
324
- ? t("navigation.expandSidebar")
325
- : t("navigation.collapseSidebar")
326
- }
327
- >
328
- <ToggleIcon className="size-4" />
329
- </button>
330
- </TooltipTrigger>
331
- <TooltipContent side="right">
332
- {collapsed
333
- ? t("navigation.expandSidebar")
334
- : t("navigation.collapseSidebar")}
335
- </TooltipContent>
336
- </Tooltip>
337
- ) : null;
267
+
268
+ const secondaryItems: AppSidebarItemDefinition[] = [
269
+ {
270
+ to: "/settings",
271
+ label: t("navigation.settings"),
272
+ icon: IconSettings,
273
+ active: location.pathname.startsWith("/settings"),
274
+ },
275
+ ];
276
+
277
+ const feedbackButton = (
278
+ <FeedbackButton variant={collapsed ? "icon" : "sidebar"} side="right" />
279
+ );
280
+
281
+ const orgSwitcher = <OrgSwitcher compact={collapsed} reserveSpace />;
282
+
338
283
  const searchButton = (
339
284
  <Tooltip>
340
285
  <TooltipTrigger asChild>
341
- <button
286
+ <Button
342
287
  type="button"
288
+ variant="ghost"
289
+ size="icon"
290
+ className="size-9 shrink-0 text-primary hover:bg-accent/60 hover:text-primary"
343
291
  onClick={openCommandMenu}
344
292
  aria-label={t("root.commandSearch")}
345
- className="flex size-8 items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
346
293
  >
347
294
  <IconSearch className="size-4" />
348
- </button>
295
+ </Button>
349
296
  </TooltipTrigger>
350
297
  <TooltipContent side="right">{t("root.commandSearch")}</TooltipContent>
351
298
  </Tooltip>
352
299
  );
353
- const feedbackButton = (
354
- <FeedbackButton
355
- variant={collapsed ? "icon" : "sidebar"}
356
- side="right"
357
- className={collapsed ? "h-8 w-8" : "min-w-0"}
358
- />
359
- );
360
300
 
361
301
  return (
362
- <aside
363
- data-collapsed={collapsed ? "true" : "false"}
364
- className={cn(
365
- "flex h-full min-w-0 shrink-0 flex-col overflow-hidden border-e border-sidebar-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-out",
366
- collapsed ? "w-12" : "w-60",
367
- )}
302
+ <AppSidebar
303
+ collapsed={collapsed}
304
+ collapsible={collapsible}
305
+ onCollapsedChange={onCollapsedChange}
306
+ brandName={APP_TITLE}
307
+ brandHref="/chat"
308
+ secondaryItems={secondaryItems}
309
+ feedback={feedbackButton}
310
+ orgSwitcher={orgSwitcher}
311
+ footerExtras={searchButton}
368
312
  >
369
- <div
370
- className={cn(
371
- "flex shrink-0 items-center border-b border-sidebar-border",
372
- collapsed ? "h-12 justify-center px-0" : "h-14 px-3",
373
- )}
374
- >
375
- <Link
376
- to="/home"
377
- onClick={(event) => {
378
- if (
379
- !collapsible ||
380
- !onCollapsedChange ||
381
- event.metaKey ||
382
- event.ctrlKey ||
383
- event.shiftKey ||
384
- event.altKey ||
385
- event.button !== 0
386
- ) {
387
- return;
388
- }
313
+ <AppSidebarNavItem
314
+ to="/chat"
315
+ label={t("navigation.chat")}
316
+ icon={IconMessageCircle}
317
+ active={isChatRoute}
318
+ onClick={(event) => {
319
+ if (
320
+ !isChatRoute &&
321
+ !event.metaKey &&
322
+ !event.ctrlKey &&
323
+ !event.shiftKey &&
324
+ !event.altKey
325
+ ) {
389
326
  event.preventDefault();
390
- onCollapsedChange(!collapsed);
391
- }}
392
- className={cn(
393
- "flex min-w-0 items-center rounded outline-none focus-visible:ring-2 focus-visible:ring-ring",
394
- collapsed ? "size-7 justify-center" : "flex-1 gap-3",
395
- )}
396
- aria-label={
397
- collapsible && onCollapsedChange
398
- ? collapsed
399
- ? t("navigation.expandSidebar")
400
- : t("navigation.collapseSidebar")
401
- : collapsed
402
- ? APP_TITLE
403
- : undefined
327
+ navigateWithAgentChatViewTransition(navigate, "/chat");
404
328
  }
405
- >
406
- <AgentNativeIcon
407
- aria-hidden="true"
408
- className="h-3.5 w-6 shrink-0 text-sidebar-accent-foreground"
409
- />
410
- <div className={cn("min-w-0", collapsed && "sr-only")}>
411
- <p className="truncate text-sm font-semibold text-sidebar-accent-foreground">
412
- {APP_TITLE}
413
- </p>
414
- </div>
415
- </Link>
416
- </div>
417
-
418
- <nav
419
- className={cn(
420
- "flex-1 overflow-y-auto",
421
- collapsed ? "px-0 py-2" : "px-2 py-3",
422
- )}
423
- >
424
- <div className={cn("grid", collapsed ? "gap-0" : "gap-1")}>
425
- {navItems.map((item) => {
426
- const Icon = item.icon;
427
- const isActive =
428
- item.href === "/chat"
429
- ? isChatRoute
430
- : item.href === "/factory"
431
- ? location.pathname === "/factory" ||
432
- location.pathname === "/new-factory"
433
- : location.pathname.startsWith(item.href);
434
- const link = (
435
- <Link
436
- to={item.href}
437
- onClick={(event) => {
438
- if (
439
- item.href === "/chat" &&
440
- !isChatRoute &&
441
- !event.metaKey &&
442
- !event.ctrlKey &&
443
- !event.shiftKey &&
444
- !event.altKey
445
- ) {
446
- event.preventDefault();
447
- navigateWithAgentChatViewTransition(navigate, "/chat");
448
- }
449
- }}
450
- className={navClass({ isActive })}
451
- aria-current={isActive ? "page" : undefined}
452
- aria-label={collapsed ? t(item.labelKey) : undefined}
453
- >
454
- <Icon className="size-4 shrink-0" />
455
- <span className={collapsed ? "sr-only" : "truncate"}>
456
- {t(item.labelKey)}
457
- </span>
458
- </Link>
459
- );
460
- return (
461
- <div key={item.href}>
462
- {collapsed ? (
463
- <Tooltip>
464
- <TooltipTrigger asChild>{link}</TooltipTrigger>
465
- <TooltipContent side="right">
466
- {t(item.labelKey)}
467
- </TooltipContent>
468
- </Tooltip>
469
- ) : (
470
- link
471
- )}
472
- {!collapsed && item.view === "chat" ? (
473
- <ChatThreadsSection open={isChatRoute} />
474
- ) : null}
475
- </div>
476
- );
477
- })}
478
- </div>
479
- </nav>
329
+ }}
330
+ />
331
+ {!collapsed && <ChatThreadsSection open={isChatRoute} />}
480
332
 
481
- <div className={cn("mt-auto shrink-0", collapsed && "py-2")}>
482
- <nav
483
- className={cn(
484
- "grid",
485
- collapsed ? "gap-0 px-1 py-1" : "gap-1 px-2 py-1",
486
- )}
487
- >
488
- {bottomNavItems.map((item) => {
489
- const Icon = item.icon;
490
- const isActive = location.pathname.startsWith(item.href);
491
- const link = (
492
- <Link
493
- to={item.href}
494
- className={navClass({ isActive })}
495
- aria-current={isActive ? "page" : undefined}
496
- aria-label={collapsed ? t(item.labelKey) : undefined}
497
- >
498
- <Icon className="size-4 shrink-0" />
499
- <span className={collapsed ? "sr-only" : "truncate"}>
500
- {t(item.labelKey)}
501
- </span>
502
- </Link>
503
- );
504
- return collapsed ? (
505
- <Tooltip key={item.href}>
506
- <TooltipTrigger asChild>{link}</TooltipTrigger>
507
- <TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
508
- </Tooltip>
509
- ) : (
510
- <div key={item.href}>{link}</div>
511
- );
512
- })}
513
- </nav>
333
+ <AppSidebarNavItem
334
+ to="/factory"
335
+ label={t("navigation.triage")}
336
+ icon={IconGitPullRequest}
337
+ active={
338
+ location.pathname === "/factory" ||
339
+ location.pathname === "/new-factory"
340
+ }
341
+ />
514
342
 
515
- <div
516
- className={cn(
517
- collapsed ? "px-1 py-1 empty:hidden" : "px-3 py-2 empty:hidden",
518
- )}
519
- >
520
- <OrgSwitcher
521
- reserveSpace
522
- className={
523
- collapsed
524
- ? "h-8 justify-center px-0 [&>span]:sr-only [&>svg:last-child]:hidden"
525
- : undefined
526
- }
527
- />
528
- </div>
529
-
530
- <SidebarFooterActions
531
- collapsed={collapsed}
532
- feedback={feedbackButton}
533
- search={searchButton}
534
- collapse={collapseButton}
535
- />
536
- </div>
537
- </aside>
343
+ <AppSidebarNavItem
344
+ to="/agents"
345
+ label={t("navigation.agents")}
346
+ icon={IconHierarchy2}
347
+ active={location.pathname.startsWith("/agents")}
348
+ />
349
+ </AppSidebar>
538
350
  );
539
351
  }