@agent-native/core 0.178.0 → 0.178.1-nightly-20260909221943

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 (88) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/.agents/skills/dictate/SKILL.md +1 -0
  3. package/corpus/templates/clips/DESIGN.md +10 -7
  4. package/corpus/templates/clips/actions/list-organization-state.ts +56 -3
  5. package/corpus/templates/clips/actions/list-recordings.ts +2 -0
  6. package/corpus/templates/clips/actions/search-dictations.ts +81 -0
  7. package/corpus/templates/clips/app/components/agent-destination-logos.tsx +50 -0
  8. package/corpus/templates/clips/app/components/bug-report/bug-report-dialog.tsx +60 -0
  9. package/corpus/templates/clips/app/components/bug-report/bug-report-form.tsx +206 -0
  10. package/corpus/templates/clips/app/components/clips-command-menu.tsx +653 -0
  11. package/corpus/templates/clips/app/components/library/empty-state.tsx +52 -17
  12. package/corpus/templates/clips/app/components/library/folder-card.tsx +34 -0
  13. package/corpus/templates/clips/app/components/library/folder-tree.tsx +109 -64
  14. package/corpus/templates/clips/app/components/library/library-action-hrefs.ts +27 -0
  15. package/corpus/templates/clips/app/components/library/library-grid.tsx +295 -103
  16. package/corpus/templates/clips/app/components/library/library-layout.tsx +381 -203
  17. package/corpus/templates/clips/app/components/library/library-primary-actions.tsx +48 -0
  18. package/corpus/templates/clips/app/components/library/page-header.tsx +48 -8
  19. package/corpus/templates/clips/app/components/library/recording-card.tsx +58 -55
  20. package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -19
  21. package/corpus/templates/clips/app/components/library/sidebar-feedback-button.tsx +48 -0
  22. package/corpus/templates/clips/app/components/player/comments-panel.tsx +2 -2
  23. package/corpus/templates/clips/app/components/player/share-dialog.tsx +344 -260
  24. package/corpus/templates/clips/app/components/player/viewer-controls.tsx +2 -2
  25. package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +0 -33
  26. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -1
  27. package/corpus/templates/clips/app/components/ui/tabs.tsx +1 -1
  28. package/corpus/templates/clips/app/hooks/use-command-search.ts +53 -0
  29. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +32 -13
  30. package/corpus/templates/clips/app/hooks/use-upload-video-picker.tsx +1 -0
  31. package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
  32. package/corpus/templates/clips/app/lib/agent-share.ts +16 -0
  33. package/corpus/templates/clips/app/lib/command-events.ts +7 -0
  34. package/corpus/templates/clips/app/root.tsx +6 -82
  35. package/corpus/templates/clips/app/routes/_app.dictate.tsx +25 -5
  36. package/corpus/templates/clips/app/routes/_app.library._index.tsx +2 -30
  37. package/corpus/templates/clips/app/routes/_app.library.folder.$folderId.tsx +13 -2
  38. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +4 -17
  39. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +111 -114
  40. package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.folder.$folderId.tsx +25 -2
  41. package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.tsx +14 -61
  42. package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +34 -24
  43. package/corpus/templates/clips/app/routes/_app.trash.tsx +1 -1
  44. package/corpus/templates/clips/app/routes/_app.tsx +2 -4
  45. package/corpus/templates/clips/app/routes/bug-report.tsx +11 -189
  46. package/corpus/templates/clips/app/routes/share.$shareId.tsx +148 -123
  47. package/corpus/templates/clips/changelog/2026-09-08-comments-and-desktop-window-controls.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-09-08-global-command-search.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-09-09-agent-sidebar-fits-below-toolbar.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-09-09-desktop-switches-stay-clear-in-dark-mode.md +6 -0
  51. package/corpus/templates/clips/changelog/2026-09-09-recording-agent-uses-global-panel.md +6 -0
  52. package/corpus/templates/clips/desktop/src/app.tsx +2 -2
  53. package/corpus/templates/clips/desktop/src/components/MediaDeviceRow.tsx +5 -3
  54. package/corpus/templates/clips/desktop/src/components/SourceRow.tsx +1 -0
  55. package/corpus/templates/clips/desktop/src/components/Switch.tsx +2 -5
  56. package/corpus/templates/clips/desktop/src/components/ui/switch.tsx +21 -3
  57. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +72 -52
  58. package/corpus/templates/clips/desktop/src/styles.css +18 -19
  59. package/corpus/templates/clips/desktop/src/tailwind.css +3 -0
  60. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +18 -10
  61. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +3 -5
  62. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +14 -3
  63. package/corpus/templates/design/AGENTS.md +2 -1
  64. package/corpus/templates/design/actions/export-png.ts +119 -0
  65. package/corpus/templates/design/actions/take-design-screenshot.ts +47 -13
  66. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -1
  67. package/corpus/templates/factory/actions/dispatch-factory-item.ts +51 -22
  68. package/corpus/templates/factory/actions/list-triage-items.ts +21 -11
  69. package/corpus/templates/factory/actions/poll-slack-channel.ts +7 -2
  70. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-keeps-claimed-markers-after-poll.md +6 -0
  71. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-preserves-started-claimed-threads.md +6 -0
  72. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-skips-claimed-parents.md +6 -0
  73. package/corpus/templates/factory/server/lib/factory-automation-config.ts +1 -1
  74. package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +47 -0
  75. package/corpus/templates/factory/server/plugins/agent-chat.ts +5 -2
  76. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +5 -4
  77. package/corpus/templates/factory/server/triage/review-skill-alignment.ts +12 -7
  78. package/corpus/templates/factory/server/triage/slack-review-window.ts +39 -0
  79. package/dist/client/CommandMenu.js +13 -1
  80. package/dist/client/analytics.js +10 -0
  81. package/dist/collab/routes.d.ts +1 -1
  82. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  83. package/dist/notifications/routes.d.ts +2 -2
  84. package/dist/observability/routes.d.ts +5 -5
  85. package/dist/vite/client.js +25 -7
  86. package/dist/vite/sentry-source-maps.d.ts +12 -0
  87. package/dist/vite/sentry-source-maps.js +105 -0
  88. package/package.json +2 -1
@@ -25,24 +25,22 @@ import {
25
25
  IconUsersGroup,
26
26
  IconBrandChrome,
27
27
  IconDownload,
28
+ IconChevronDown,
28
29
  IconMenu2,
29
30
  IconLayoutSidebarLeftCollapse,
30
31
  IconLayoutSidebarLeftExpand,
31
- IconLayoutSidebarRight,
32
32
  IconShare,
33
33
  IconDots,
34
34
  IconEdit,
35
35
  } from "@tabler/icons-react";
36
- import {
37
- Fragment,
38
- ReactNode,
39
- useEffect,
40
- useMemo,
41
- useRef,
42
- useState,
43
- } from "react";
36
+ import { ReactNode, useEffect, useMemo, useRef, useState } from "react";
44
37
  import { NavLink, useLocation, useNavigate, useParams } from "react-router";
45
38
 
39
+ import {
40
+ Collapsible,
41
+ CollapsibleContent,
42
+ CollapsibleTrigger,
43
+ } from "@/components/ui/collapsible";
46
44
  import {
47
45
  ContextMenu,
48
46
  ContextMenuContent,
@@ -78,15 +76,30 @@ import { cn } from "@/lib/utils";
78
76
 
79
77
  import { FolderTree, type FolderNode } from "./folder-tree";
80
78
  import { PageHeaderSlotProvider } from "./page-header";
79
+ import { SidebarFeedbackButton } from "./sidebar-feedback-button";
81
80
  import { SpaceDialogs } from "./space-dialogs";
82
81
 
83
82
  interface LibraryLayoutProps {
84
83
  children: ReactNode;
85
- /** Disable the workspace Agent rail when a route embeds Agent in its own panel. */
86
- showAgentSidebar?: boolean;
87
84
  }
88
85
 
89
86
  const SIDEBAR_COLLAPSED_STORAGE_KEY = "clips:left-sidebar-collapsed";
87
+ type SidebarGroupKey = "library" | "spaces";
88
+
89
+ function isSidebarGroupActive(
90
+ pathname: string,
91
+ group: SidebarGroupKey,
92
+ matchesRoute: boolean,
93
+ ) {
94
+ if (!matchesRoute) return false;
95
+ if (group === "library" && pathname.startsWith("/library/folder/")) {
96
+ return false;
97
+ }
98
+ if (group === "spaces" && pathname.startsWith("/spaces/")) {
99
+ return false;
100
+ }
101
+ return true;
102
+ }
90
103
 
91
104
  function readSidebarCollapsedPreference() {
92
105
  if (typeof window === "undefined") return false;
@@ -101,18 +114,81 @@ function readSidebarCollapsedPreference() {
101
114
  }
102
115
 
103
116
  function ClipsAgentToggleButton() {
117
+ return <AgentToggleButton showWhenOpen />;
118
+ }
119
+
120
+ interface ExpandedSidebarNavGroupProps {
121
+ to: string;
122
+ label: string;
123
+ icon: React.ComponentType<{ className?: string }>;
124
+ active: boolean;
125
+ count?: number;
126
+ open: boolean;
127
+ onOpenChange: (open: boolean) => void;
128
+ children: ReactNode;
129
+ }
130
+
131
+ function ExpandedSidebarNavGroup({
132
+ to,
133
+ label,
134
+ icon: Icon,
135
+ active,
136
+ count,
137
+ open,
138
+ onOpenChange,
139
+ children,
140
+ }: ExpandedSidebarNavGroupProps) {
141
+ const t = useT();
142
+
104
143
  return (
105
- <AgentToggleButton
106
- showWhenOpen
107
- icon={<IconLayoutSidebarRight className="size-5" aria-hidden />}
108
- />
144
+ <Collapsible
145
+ open={open}
146
+ onOpenChange={onOpenChange}
147
+ className="group/sidebar-nav"
148
+ >
149
+ <div
150
+ className={cn(
151
+ "group flex items-center rounded",
152
+ active
153
+ ? "bg-primary/10 font-medium text-primary"
154
+ : "text-primary hover:bg-accent/60",
155
+ )}
156
+ >
157
+ <NavLink
158
+ to={to}
159
+ className="flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-xs text-primary"
160
+ >
161
+ <Icon className="size-4 shrink-0 text-primary" />
162
+ <span className="flex-1 truncate text-primary">{label}</span>
163
+ {count !== undefined && count > 0 && (
164
+ <span className="shrink-0 tabular-nums text-[11px] text-primary/80">
165
+ {count}
166
+ </span>
167
+ )}
168
+ </NavLink>
169
+ <CollapsibleTrigger asChild>
170
+ <button
171
+ type="button"
172
+ aria-label={`${t(open ? "settings.collapse" : "settings.expand")}: ${label}`}
173
+ className="me-1 flex size-7 shrink-0 items-center justify-center rounded text-primary hover:bg-accent hover:text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
174
+ >
175
+ <IconChevronDown
176
+ className={cn(
177
+ "size-3.5 transition-transform motion-reduce:transition-none",
178
+ open && "rotate-180",
179
+ )}
180
+ />
181
+ </button>
182
+ </CollapsibleTrigger>
183
+ </div>
184
+ <CollapsibleContent className="clips-collapsible-content">
185
+ <div className="ms-3.5 border-s border-border/70 ps-2">{children}</div>
186
+ </CollapsibleContent>
187
+ </Collapsible>
109
188
  );
110
189
  }
111
190
 
112
- export function LibraryLayout({
113
- children,
114
- showAgentSidebar = true,
115
- }: LibraryLayoutProps) {
191
+ export function LibraryLayout({ children }: LibraryLayoutProps) {
116
192
  const location = useLocation();
117
193
  const navigate = useNavigate();
118
194
  const t = useT();
@@ -170,9 +246,26 @@ export function LibraryLayout({
170
246
  parentId: f.parentId ?? null,
171
247
  spaceId: f.spaceId ?? null,
172
248
  name: f.name,
249
+ recordingCount: Number(f.recordingCount ?? 0),
173
250
  })),
174
251
  [libFolders],
175
252
  );
253
+ const spaceFolderLists = useMemo(() => {
254
+ const foldersBySpace = new Map<string, FolderNode[]>();
255
+ for (const folder of libFolders?.folders ?? []) {
256
+ if (!folder.spaceId) continue;
257
+ const folders = foldersBySpace.get(folder.spaceId) ?? [];
258
+ folders.push({
259
+ id: folder.id,
260
+ parentId: folder.parentId ?? null,
261
+ spaceId: folder.spaceId,
262
+ name: folder.name,
263
+ recordingCount: Number(folder.recordingCount ?? 0),
264
+ });
265
+ foldersBySpace.set(folder.spaceId, folders);
266
+ }
267
+ return foldersBySpace;
268
+ }, [libFolders]);
176
269
 
177
270
  const [sidebarOpen, setSidebarOpen] = useState(false);
178
271
  const mobileSidebarRef = useRef<HTMLElement | null>(null);
@@ -180,6 +273,14 @@ export function LibraryLayout({
180
273
  const [sidebarCollapsed, setSidebarCollapsed] = useState(
181
274
  readSidebarCollapsedPreference,
182
275
  );
276
+ const [expandedSidebarGroups, setExpandedSidebarGroups] = useState<
277
+ Record<SidebarGroupKey, boolean>
278
+ >(() => ({
279
+ library:
280
+ location.pathname.startsWith("/library") ||
281
+ location.pathname.startsWith("/r/"),
282
+ spaces: location.pathname.startsWith("/spaces"),
283
+ }));
183
284
  const [headerSlot, setHeaderSlot] = useState<HTMLElement | null>(null);
184
285
  const showCollapsedSidebar = sidebarCollapsed && !isMobile;
185
286
  const workspaceUtilityLinks = [
@@ -215,7 +316,7 @@ export function LibraryLayout({
215
316
  ? t("navigation.expandSidebar")
216
317
  : t("navigation.collapseSidebar")
217
318
  }
218
- className="flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground"
319
+ className="flex size-9 shrink-0 items-center justify-center rounded-md bg-transparent text-primary hover:bg-accent/60 hover:text-primary"
219
320
  onClick={() => setSidebarCollapsed((value) => !value)}
220
321
  >
221
322
  {showCollapsedSidebar ? (
@@ -240,6 +341,15 @@ export function LibraryLayout({
240
341
  useEffect(() => {
241
342
  setSidebarOpen(false);
242
343
  }, [location.pathname]);
344
+ useEffect(() => {
345
+ setExpandedSidebarGroups((groups) => ({
346
+ library:
347
+ groups.library ||
348
+ location.pathname.startsWith("/library") ||
349
+ location.pathname.startsWith("/r/"),
350
+ spaces: groups.spaces || location.pathname.startsWith("/spaces"),
351
+ }));
352
+ }, [location.pathname]);
243
353
  useEffect(() => {
244
354
  if (!isMobile || !sidebarOpen) return;
245
355
 
@@ -312,7 +422,8 @@ export function LibraryLayout({
312
422
  to: "/library",
313
423
  label: t("navigation.library"),
314
424
  icon: IconInbox,
315
- match: (p) => p.startsWith("/library") || p.startsWith("/r/"),
425
+ match: (p) =>
426
+ p === "/home" || p.startsWith("/library") || p.startsWith("/r/"),
316
427
  count: libraryCount,
317
428
  },
318
429
  {
@@ -326,7 +437,7 @@ export function LibraryLayout({
326
437
  to: "/spaces",
327
438
  label: t("navigation.spaces"),
328
439
  icon: IconUsersGroup,
329
- match: (p) => p.startsWith("/spaces"),
440
+ match: (p) => p === "/spaces" || p.startsWith("/spaces/"),
330
441
  },
331
442
  ...(meetingsExperimentEnabled
332
443
  ? [
@@ -385,20 +496,20 @@ export function LibraryLayout({
385
496
  "group flex items-center rounded",
386
497
  active
387
498
  ? "bg-primary/10 font-medium text-primary"
388
- : "text-foreground hover:bg-accent/60",
499
+ : "text-primary hover:bg-accent/60",
389
500
  )}
390
501
  >
391
502
  <NavLink
392
503
  to={to}
393
- className="flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-xs"
504
+ className="flex min-w-0 flex-1 items-center gap-2 px-2 py-1.5 text-xs text-primary"
394
505
  >
395
- <Icon className="size-4 shrink-0" />
396
- <span className="flex-1 truncate">{label}</span>
506
+ <Icon className="size-4 shrink-0 text-primary" />
507
+ <span className="flex-1 truncate text-primary">{label}</span>
397
508
  {count !== undefined && count > 0 && (
398
509
  <span
399
510
  className={cn(
400
511
  "shrink-0 tabular-nums text-[11px]",
401
- active ? "text-primary/80" : "text-muted-foreground",
512
+ "text-primary/80",
402
513
  )}
403
514
  >
404
515
  {count}
@@ -424,12 +535,12 @@ export function LibraryLayout({
424
535
  to={to}
425
536
  aria-label={label}
426
537
  className={cn(
427
- "flex size-9 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground",
538
+ "flex size-9 items-center justify-center rounded-md text-primary hover:bg-accent/60 hover:text-primary",
428
539
  active &&
429
540
  "bg-primary/10 text-primary hover:bg-primary/10 hover:text-primary",
430
541
  )}
431
542
  >
432
- <Icon className="size-4" />
543
+ <Icon className="size-4 text-primary" />
433
544
  </NavLink>
434
545
  </TooltipTrigger>
435
546
  <TooltipContent side="right">{label}</TooltipContent>
@@ -437,6 +548,31 @@ export function LibraryLayout({
437
548
  );
438
549
  };
439
550
 
551
+ const renderExpandedNavGroup = (
552
+ item: (typeof navItems)[number],
553
+ group: SidebarGroupKey,
554
+ children: ReactNode,
555
+ ) => (
556
+ <ExpandedSidebarNavGroup
557
+ key={item.to}
558
+ to={item.to}
559
+ label={item.label}
560
+ icon={item.icon}
561
+ active={isSidebarGroupActive(
562
+ location.pathname,
563
+ group,
564
+ item.match(location.pathname),
565
+ )}
566
+ count={item.count}
567
+ open={expandedSidebarGroups[group]}
568
+ onOpenChange={(open) =>
569
+ setExpandedSidebarGroups((groups) => ({ ...groups, [group]: open }))
570
+ }
571
+ >
572
+ {children}
573
+ </ExpandedSidebarNavGroup>
574
+ );
575
+
440
576
  const pageContent = (
441
577
  <div className="flex min-h-0 min-w-0 flex-1 flex-col">
442
578
  <InvitationBanner />
@@ -489,16 +625,16 @@ export function LibraryLayout({
489
625
  to="/library"
490
626
  aria-label={t("navigation.brand")}
491
627
  className={cn(
492
- "flex min-w-0 translate-y-0.5 items-center gap-2 rounded text-start outline-none focus-visible:ring-2 focus-visible:ring-ring",
628
+ "flex min-w-0 items-center gap-2 rounded text-start outline-none focus-visible:ring-2 focus-visible:ring-ring",
493
629
  showCollapsedSidebar ? "size-8 justify-center" : "shrink-0",
494
630
  )}
495
631
  >
496
632
  <AgentNativeIcon
497
633
  aria-hidden="true"
498
- className="h-3.5 w-6 shrink-0 text-foreground"
634
+ className="h-3.5 w-6 shrink-0 text-primary"
499
635
  />
500
636
  {!showCollapsedSidebar && (
501
- <span className="truncate text-sm font-semibold text-foreground">
637
+ <span className="truncate text-sm font-semibold text-primary">
502
638
  {t("navigation.brand")}
503
639
  </span>
504
640
  )}
@@ -515,143 +651,168 @@ export function LibraryLayout({
515
651
  </nav>
516
652
  ) : (
517
653
  <nav className="space-y-0.5 px-2 py-3">
518
- {primaryNavItems.map((item) => (
519
- <Fragment key={item.to}>
520
- {renderExpandedNavItem(item)}
521
- {item.to === "/library" && libFolderList.length > 0 && (
522
- <div className="ms-4 border-s border-border/70 ps-1">
523
- <FolderTree
524
- folders={libFolderList}
525
- organizationId={currentOrganizationId}
526
- spaceId={null}
527
- buildPath={(id) => `/library/folder/${id}`}
528
- activeFolderId={folderId ?? null}
529
- />
530
- </div>
531
- )}
532
- {item.to === "/spaces" &&
533
- (spaces?.spaces ?? []).length > 0 && (
534
- <ul className="ms-4 space-y-0.5 border-s border-border/70 ps-1">
535
- {(spaces?.spaces ?? []).map((s: any) => {
536
- const active = spaceId === s.id;
537
- return (
538
- <li key={s.id}>
539
- <ContextMenu>
540
- <ContextMenuTrigger asChild>
541
- <div
542
- className={cn(
543
- "group flex items-center gap-2 rounded px-2 py-1 text-xs",
544
- active
545
- ? "bg-primary/10 text-primary"
546
- : "text-foreground hover:bg-accent/60",
547
- )}
654
+ {primaryNavItems.map((item) => {
655
+ if (item.to === "/library" && libFolderList.length > 0) {
656
+ return renderExpandedNavGroup(
657
+ item,
658
+ "library",
659
+ <FolderTree
660
+ compact
661
+ folders={libFolderList}
662
+ organizationId={currentOrganizationId}
663
+ spaceId={null}
664
+ buildPath={(id) => `/library/folder/${id}`}
665
+ activeFolderId={folderId ?? null}
666
+ />,
667
+ );
668
+ }
669
+
670
+ if (
671
+ item.to === "/spaces" &&
672
+ (spaces?.spaces ?? []).length > 0
673
+ ) {
674
+ return renderExpandedNavGroup(
675
+ item,
676
+ "spaces",
677
+ <ul className="space-y-0.5">
678
+ {(spaces?.spaces ?? []).map((s: any) => {
679
+ const active = spaceId === s.id;
680
+ const spaceFolders = spaceFolderLists.get(s.id) ?? [];
681
+ return (
682
+ <li key={s.id}>
683
+ <ContextMenu>
684
+ <ContextMenuTrigger asChild>
685
+ <div
686
+ className={cn(
687
+ "group flex items-center gap-2 rounded px-1.5 py-1 text-xs",
688
+ active
689
+ ? "bg-primary/10 text-primary"
690
+ : "text-primary hover:bg-accent/60",
691
+ )}
692
+ >
693
+ <NavLink
694
+ to={`/spaces/${s.id}`}
695
+ className="flex min-w-0 flex-1 items-center gap-2 text-primary"
548
696
  >
549
- <NavLink
550
- to={`/spaces/${s.id}`}
551
- className="flex min-w-0 flex-1 items-center gap-2"
697
+ <div
698
+ className="flex size-4 shrink-0 items-center justify-center rounded text-[10px]"
699
+ style={{
700
+ background:
701
+ s.color ?? "hsl(var(--primary))",
702
+ color: "hsl(var(--primary-foreground))",
703
+ }}
552
704
  >
553
- <div
554
- className="flex size-4 shrink-0 items-center justify-center rounded text-[10px]"
555
- style={{
556
- background:
557
- s.color ?? "hsl(var(--primary))",
558
- color:
559
- "hsl(var(--primary-foreground))",
560
- }}
561
- >
562
- {s.iconEmoji ??
563
- s.name.slice(0, 1).toUpperCase()}
564
- </div>
565
- <span className="truncate">{s.name}</span>
566
- </NavLink>
567
- {canManageOrg && (
568
- <DropdownMenu>
569
- <DropdownMenuTrigger asChild>
570
- <button
571
- type="button"
572
- aria-label={`${s.name}: ${t("root.commandActions")}`}
573
- title={`${s.name}: ${t("root.commandActions")}`}
574
- className="rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100"
575
- >
576
- <IconDots className="size-3.5" />
577
- </button>
578
- </DropdownMenuTrigger>
579
- <DropdownMenuContent
580
- align="start"
581
- side="right"
582
- >
583
- <DropdownMenuItem
584
- onSelect={() => {
585
- setTimeout(() => {
586
- setRenameSpaceValue(s.name);
587
- setRenameSpaceId(s.id);
588
- }, 0);
589
- }}
590
- >
591
- <IconEdit className="me-2 size-3.5" />
592
- {t("spaceDialog.renameSpace")}
593
- </DropdownMenuItem>
594
- <DropdownMenuItem
595
- onSelect={() => {
596
- setTimeout(() => {
597
- setDeleteSpaceId(s.id);
598
- setDeleteSpaceName(s.name);
599
- }, 0);
600
- }}
601
- className="text-destructive"
602
- >
603
- <IconTrash className="me-2 size-3.5" />
604
- {t("spaceDialog.deleteSpace")}
605
- </DropdownMenuItem>
606
- </DropdownMenuContent>
607
- </DropdownMenu>
608
- )}
609
- </div>
610
- </ContextMenuTrigger>
611
- <ContextMenuContent>
612
- <ContextMenuItem asChild>
613
- <NavLink to={`/spaces/${s.id}`}>
614
- <IconUsersGroup className="me-2 size-3.5" />
615
- {t("clipsFinalRaw.view")}
616
- </NavLink>
617
- </ContextMenuItem>
705
+ {s.iconEmoji ??
706
+ s.name.slice(0, 1).toUpperCase()}
707
+ </div>
708
+ <span className="truncate text-primary">
709
+ {s.name}
710
+ </span>
711
+ </NavLink>
618
712
  {canManageOrg && (
619
- <>
620
- <ContextMenuSeparator />
621
- <ContextMenuItem
622
- onSelect={() => {
623
- setTimeout(() => {
624
- setRenameSpaceValue(s.name);
625
- setRenameSpaceId(s.id);
626
- }, 0);
627
- }}
628
- >
629
- <IconEdit className="me-2 size-3.5" />
630
- {t("spaceDialog.renameSpace")}
631
- </ContextMenuItem>
632
- <ContextMenuItem
633
- onSelect={() => {
634
- setTimeout(() => {
635
- setDeleteSpaceId(s.id);
636
- setDeleteSpaceName(s.name);
637
- }, 0);
638
- }}
639
- className="text-destructive focus:text-destructive"
713
+ <DropdownMenu>
714
+ <DropdownMenuTrigger asChild>
715
+ <button
716
+ type="button"
717
+ aria-label={`${s.name}: ${t("root.commandActions")}`}
718
+ title={`${s.name}: ${t("root.commandActions")}`}
719
+ className="rounded p-0.5 text-primary opacity-0 transition-opacity hover:bg-accent hover:text-primary focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100"
720
+ >
721
+ <IconDots className="size-3.5" />
722
+ </button>
723
+ </DropdownMenuTrigger>
724
+ <DropdownMenuContent
725
+ align="start"
726
+ side="right"
640
727
  >
641
- <IconTrash className="me-2 size-3.5" />
642
- {t("spaceDialog.deleteSpace")}
643
- </ContextMenuItem>
644
- </>
728
+ <DropdownMenuItem
729
+ onSelect={() => {
730
+ setTimeout(() => {
731
+ setRenameSpaceValue(s.name);
732
+ setRenameSpaceId(s.id);
733
+ }, 0);
734
+ }}
735
+ >
736
+ <IconEdit className="me-2 size-3.5" />
737
+ {t("spaceDialog.renameSpace")}
738
+ </DropdownMenuItem>
739
+ <DropdownMenuItem
740
+ onSelect={() => {
741
+ setTimeout(() => {
742
+ setDeleteSpaceId(s.id);
743
+ setDeleteSpaceName(s.name);
744
+ }, 0);
745
+ }}
746
+ className="text-destructive"
747
+ >
748
+ <IconTrash className="me-2 size-3.5" />
749
+ {t("spaceDialog.deleteSpace")}
750
+ </DropdownMenuItem>
751
+ </DropdownMenuContent>
752
+ </DropdownMenu>
645
753
  )}
646
- </ContextMenuContent>
647
- </ContextMenu>
648
- </li>
649
- );
650
- })}
651
- </ul>
652
- )}
653
- </Fragment>
654
- ))}
754
+ </div>
755
+ </ContextMenuTrigger>
756
+ <ContextMenuContent>
757
+ <ContextMenuItem asChild>
758
+ <NavLink to={`/spaces/${s.id}`}>
759
+ <IconUsersGroup className="me-2 size-3.5" />
760
+ {t("clipsFinalRaw.view")}
761
+ </NavLink>
762
+ </ContextMenuItem>
763
+ {canManageOrg && (
764
+ <>
765
+ <ContextMenuSeparator />
766
+ <ContextMenuItem
767
+ onSelect={() => {
768
+ setTimeout(() => {
769
+ setRenameSpaceValue(s.name);
770
+ setRenameSpaceId(s.id);
771
+ }, 0);
772
+ }}
773
+ >
774
+ <IconEdit className="me-2 size-3.5" />
775
+ {t("spaceDialog.renameSpace")}
776
+ </ContextMenuItem>
777
+ <ContextMenuItem
778
+ onSelect={() => {
779
+ setTimeout(() => {
780
+ setDeleteSpaceId(s.id);
781
+ setDeleteSpaceName(s.name);
782
+ }, 0);
783
+ }}
784
+ className="text-destructive focus:text-destructive"
785
+ >
786
+ <IconTrash className="me-2 size-3.5" />
787
+ {t("spaceDialog.deleteSpace")}
788
+ </ContextMenuItem>
789
+ </>
790
+ )}
791
+ </ContextMenuContent>
792
+ </ContextMenu>
793
+ {spaceFolders.length > 0 && (
794
+ <div className="ms-3 border-s border-border/70 ps-2">
795
+ <FolderTree
796
+ compact
797
+ folders={spaceFolders}
798
+ organizationId={currentOrganizationId}
799
+ spaceId={s.id}
800
+ buildPath={(id) =>
801
+ `/spaces/${s.id}/folder/${id}`
802
+ }
803
+ activeFolderId={folderId ?? null}
804
+ />
805
+ </div>
806
+ )}
807
+ </li>
808
+ );
809
+ })}
810
+ </ul>,
811
+ );
812
+ }
813
+
814
+ return renderExpandedNavItem(item);
815
+ })}
655
816
 
656
817
  <div className="mt-3 space-y-0.5 border-t border-border/70 pt-3">
657
818
  {lifecycleNavItems.map(renderExpandedNavItem)}
@@ -662,23 +823,33 @@ export function LibraryLayout({
662
823
 
663
824
  <div
664
825
  className={cn(
665
- "shrink-0 border-t border-border p-2 empty:hidden",
666
- showCollapsedSidebar
667
- ? "flex flex-col items-center gap-1"
668
- : "flex items-center gap-0.5",
826
+ "shrink-0 border-t border-border p-2",
827
+ showCollapsedSidebar ? "space-y-1" : "space-y-1.5",
669
828
  )}
670
829
  >
671
- <OrgSwitcher
672
- compact={showCollapsedSidebar}
830
+ <SidebarFeedbackButton collapsed={showCollapsedSidebar} />
831
+ <div
832
+ data-sidebar-footer-utilities
673
833
  className={cn(
674
- "bg-transparent hover:bg-accent/60",
675
- !showCollapsedSidebar && "min-w-0 flex-1",
834
+ showCollapsedSidebar
835
+ ? "flex flex-col items-center gap-1"
836
+ : "flex items-center gap-0.5",
676
837
  )}
677
- settingsPath="/settings/organization"
678
- currentAppId="clips"
679
- utilityLinks={workspaceUtilityLinks}
680
- />
681
- {collapseButton}
838
+ >
839
+ <OrgSwitcher
840
+ compact={showCollapsedSidebar}
841
+ className={cn(
842
+ "!bg-transparent !text-primary hover:!bg-accent/60 hover:!text-primary",
843
+ showCollapsedSidebar
844
+ ? "!size-9 !p-0 [&>svg]:!size-4"
845
+ : "min-w-0 flex-1",
846
+ )}
847
+ settingsPath="/settings/organization"
848
+ currentAppId="clips"
849
+ utilityLinks={workspaceUtilityLinks}
850
+ />
851
+ {collapseButton}
852
+ </div>
682
853
  </div>
683
854
  </aside>
684
855
 
@@ -700,34 +871,41 @@ export function LibraryLayout({
700
871
  ref={setHeaderSlot}
701
872
  className="flex min-w-0 flex-1 items-center gap-3 overflow-hidden"
702
873
  />
703
- {showAgentSidebar ? (
704
- <div className="ms-1 flex items-center border-s border-border ps-2">
705
- <ClipsAgentToggleButton />
706
- </div>
707
- ) : null}
874
+ <div className="ms-1 flex items-center border-s border-border ps-2">
875
+ <ClipsAgentToggleButton />
876
+ </div>
708
877
  </header>
709
878
  )}
710
- <div className="flex min-h-0 flex-1 overflow-hidden [&>.agent-sidebar-shell]:h-full [&>.agent-sidebar-shell]:min-h-0">
711
- {showAgentSidebar ? (
712
- <AgentSidebar
713
- position="right"
714
- defaultOpen={false}
715
- showCollapseButton={isMobile}
716
- emptyStateText={t("navigation.agentEmptyState")}
717
- suggestions={[
718
- t("navigation.agentSuggestionSummary"),
719
- t("navigation.agentSuggestionPricing"),
720
- t("navigation.agentSuggestionFiller"),
721
- ]}
722
- agentPageHref="/settings/agent"
723
- scope={recordingScope}
724
- browserTabId={getBrowserTabId()}
725
- >
726
- {pageContent}
727
- </AgentSidebar>
728
- ) : (
729
- pageContent
730
- )}
879
+ <div className="flex min-h-0 flex-1 overflow-hidden [--agent-native-viewport-height:100%]">
880
+ <AgentSidebar
881
+ position="right"
882
+ defaultOpen={false}
883
+ showCollapseButton={isMobile}
884
+ emptyStateText={
885
+ recordingScope
886
+ ? t("recordingPage.askAboutClip")
887
+ : t("navigation.agentEmptyState")
888
+ }
889
+ suggestions={
890
+ recordingScope
891
+ ? [
892
+ t("recordingPage.summarizeClip"),
893
+ t("recordingPage.findKeyMoments"),
894
+ t("recordingPage.listFollowUpActions"),
895
+ t("recordingPage.draftQuestions"),
896
+ ]
897
+ : [
898
+ t("navigation.agentSuggestionSummary"),
899
+ t("navigation.agentSuggestionPricing"),
900
+ t("navigation.agentSuggestionFiller"),
901
+ ]
902
+ }
903
+ agentPageHref="/settings/agent"
904
+ scope={recordingScope}
905
+ browserTabId={getBrowserTabId()}
906
+ >
907
+ {pageContent}
908
+ </AgentSidebar>
731
909
  </div>
732
910
  </div>
733
911