@handled-ai/design-system 0.8.0 → 0.9.0

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 (336) hide show
  1. package/README.md +14 -4
  2. package/dist/charts/bar-chart-component.d.ts +24 -0
  3. package/dist/charts/bar-chart-component.js +123 -0
  4. package/dist/charts/bar-chart-component.js.map +1 -0
  5. package/dist/charts/chart-tooltip.d.ts +26 -0
  6. package/dist/charts/chart-tooltip.js +69 -0
  7. package/dist/charts/chart-tooltip.js.map +1 -0
  8. package/dist/charts/chart.d.ts +64 -0
  9. package/dist/charts/chart.js +285 -0
  10. package/dist/charts/chart.js.map +1 -0
  11. package/dist/charts/donut-chart.d.ts +21 -0
  12. package/dist/charts/donut-chart.js +96 -0
  13. package/dist/charts/donut-chart.js.map +1 -0
  14. package/dist/charts/index.d.ts +11 -0
  15. package/dist/charts/index.js +10 -0
  16. package/dist/charts/index.js.map +1 -0
  17. package/dist/charts/pipeline-overview.d.ts +76 -0
  18. package/dist/charts/pipeline-overview.js +372 -0
  19. package/dist/charts/pipeline-overview.js.map +1 -0
  20. package/dist/charts/sankey-chart.d.ts +52 -0
  21. package/dist/charts/sankey-chart.js +219 -0
  22. package/dist/charts/sankey-chart.js.map +1 -0
  23. package/dist/charts/top-line-metrics.d.ts +26 -0
  24. package/dist/charts/top-line-metrics.js +224 -0
  25. package/dist/charts/top-line-metrics.js.map +1 -0
  26. package/dist/charts/trend-area-chart.d.ts +21 -0
  27. package/dist/charts/trend-area-chart.js +150 -0
  28. package/dist/charts/trend-area-chart.js.map +1 -0
  29. package/dist/charts/volume-analysis-chart.d.ts +19 -0
  30. package/dist/charts/volume-analysis-chart.js +121 -0
  31. package/dist/charts/volume-analysis-chart.js.map +1 -0
  32. package/dist/components/activity-detail.d.ts +38 -0
  33. package/dist/components/activity-detail.js +163 -0
  34. package/dist/components/activity-detail.js.map +1 -0
  35. package/dist/components/activity-log.d.ts +21 -0
  36. package/dist/components/activity-log.js +61 -0
  37. package/dist/components/activity-log.js.map +1 -0
  38. package/dist/components/agent-popover.d.ts +71 -0
  39. package/dist/components/agent-popover.js +282 -0
  40. package/dist/components/agent-popover.js.map +1 -0
  41. package/dist/components/agent-widget.d.ts +24 -0
  42. package/dist/components/agent-widget.js +117 -0
  43. package/dist/components/agent-widget.js.map +1 -0
  44. package/dist/components/avatar.d.ts +13 -0
  45. package/dist/components/avatar.js +140 -0
  46. package/dist/components/avatar.js.map +1 -0
  47. package/dist/components/badge.d.ts +12 -0
  48. package/dist/components/badge.js +75 -0
  49. package/dist/components/badge.js.map +1 -0
  50. package/dist/components/button.d.ts +13 -0
  51. package/dist/components/button.js +83 -0
  52. package/dist/components/button.js.map +1 -0
  53. package/dist/components/card.d.ts +11 -0
  54. package/dist/components/card.js +119 -0
  55. package/dist/components/card.js.map +1 -0
  56. package/dist/components/contact-list.d.ts +34 -0
  57. package/dist/components/contact-list.js +84 -0
  58. package/dist/components/contact-list.js.map +1 -0
  59. package/dist/components/dashboard-cards.d.ts +10 -0
  60. package/dist/components/dashboard-cards.js +164 -0
  61. package/dist/components/dashboard-cards.js.map +1 -0
  62. package/dist/components/data-table-display.d.ts +19 -0
  63. package/dist/components/data-table-display.js +109 -0
  64. package/dist/components/data-table-display.js.map +1 -0
  65. package/dist/components/data-table-filter.d.ts +18 -0
  66. package/dist/components/data-table-filter.js +107 -0
  67. package/dist/components/data-table-filter.js.map +1 -0
  68. package/dist/components/data-table-quick-views.d.ts +13 -0
  69. package/dist/components/data-table-quick-views.js +90 -0
  70. package/dist/components/data-table-quick-views.js.map +1 -0
  71. package/dist/components/data-table-toolbar.d.ts +18 -0
  72. package/dist/components/data-table-toolbar.js +45 -0
  73. package/dist/components/data-table-toolbar.js.map +1 -0
  74. package/dist/components/data-table.d.ts +39 -0
  75. package/dist/components/data-table.js +821 -0
  76. package/dist/components/data-table.js.map +1 -0
  77. package/dist/components/detail-view.d.ts +44 -0
  78. package/dist/components/detail-view.js +165 -0
  79. package/dist/components/detail-view.js.map +1 -0
  80. package/dist/components/dialog.d.ts +19 -0
  81. package/dist/components/dialog.js +188 -0
  82. package/dist/components/dialog.js.map +1 -0
  83. package/dist/components/dropdown-menu.d.ts +27 -0
  84. package/dist/components/dropdown-menu.js +279 -0
  85. package/dist/components/dropdown-menu.js.map +1 -0
  86. package/dist/components/entity-panel.d.ts +69 -0
  87. package/dist/components/entity-panel.js +584 -0
  88. package/dist/components/entity-panel.js.map +1 -0
  89. package/dist/components/inbox-row.d.ts +27 -0
  90. package/dist/components/inbox-row.js +139 -0
  91. package/dist/components/inbox-row.js.map +1 -0
  92. package/dist/components/inbox-toolbar.d.ts +21 -0
  93. package/dist/components/inbox-toolbar.js +203 -0
  94. package/dist/components/inbox-toolbar.js.map +1 -0
  95. package/dist/components/input.d.ts +5 -0
  96. package/dist/components/input.js +50 -0
  97. package/dist/components/input.js.map +1 -0
  98. package/dist/components/insights-filter-bar.d.ts +21 -0
  99. package/dist/components/insights-filter-bar.js +99 -0
  100. package/dist/components/insights-filter-bar.js.map +1 -0
  101. package/dist/components/item-list-display.d.ts +22 -0
  102. package/dist/components/item-list-display.js +240 -0
  103. package/dist/components/item-list-display.js.map +1 -0
  104. package/dist/components/item-list-filter.d.ts +16 -0
  105. package/dist/components/item-list-filter.js +87 -0
  106. package/dist/components/item-list-filter.js.map +1 -0
  107. package/dist/components/item-list-toolbar.d.ts +25 -0
  108. package/dist/components/item-list-toolbar.js +79 -0
  109. package/dist/components/item-list-toolbar.js.map +1 -0
  110. package/dist/components/item-list.d.ts +20 -0
  111. package/dist/components/item-list.js +702 -0
  112. package/dist/components/item-list.js.map +1 -0
  113. package/dist/components/label.d.ts +6 -0
  114. package/dist/components/label.js +55 -0
  115. package/dist/components/label.js.map +1 -0
  116. package/dist/components/message.d.ts +23 -0
  117. package/dist/components/message.js +117 -0
  118. package/dist/components/message.js.map +1 -0
  119. package/dist/components/metric-card.d.ts +25 -0
  120. package/dist/components/metric-card.js +107 -0
  121. package/dist/components/metric-card.js.map +1 -0
  122. package/dist/components/performance-metrics-table.d.ts +38 -0
  123. package/dist/components/performance-metrics-table.js +342 -0
  124. package/dist/components/performance-metrics-table.js.map +1 -0
  125. package/dist/components/preview-list.d.ts +14 -0
  126. package/dist/components/preview-list.js +83 -0
  127. package/dist/components/preview-list.js.map +1 -0
  128. package/dist/components/progress.d.ts +6 -0
  129. package/dist/components/progress.js +69 -0
  130. package/dist/components/progress.js.map +1 -0
  131. package/dist/components/quick-action-chat-area.d.ts +24 -0
  132. package/dist/components/quick-action-chat-area.js +178 -0
  133. package/dist/components/quick-action-chat-area.js.map +1 -0
  134. package/dist/components/quick-action-modal.d.ts +30 -0
  135. package/dist/components/quick-action-modal.js +288 -0
  136. package/dist/components/quick-action-modal.js.map +1 -0
  137. package/dist/components/quick-action-sidebar-nav.d.ts +51 -0
  138. package/dist/components/quick-action-sidebar-nav.js +528 -0
  139. package/dist/components/quick-action-sidebar-nav.js.map +1 -0
  140. package/dist/components/recommended-actions-section.d.ts +23 -0
  141. package/dist/components/recommended-actions-section.js +215 -0
  142. package/dist/components/recommended-actions-section.js.map +1 -0
  143. package/dist/components/report-card.d.ts +26 -0
  144. package/dist/components/report-card.js +69 -0
  145. package/dist/components/report-card.js.map +1 -0
  146. package/dist/components/score-analysis-modal.d.ts +26 -0
  147. package/dist/components/score-analysis-modal.js +141 -0
  148. package/dist/components/score-analysis-modal.js.map +1 -0
  149. package/dist/components/score-breakdown.d.ts +17 -0
  150. package/dist/components/score-breakdown.js +162 -0
  151. package/dist/components/score-breakdown.js.map +1 -0
  152. package/dist/components/score-feedback.d.ts +40 -0
  153. package/dist/components/score-feedback.js +209 -0
  154. package/dist/components/score-feedback.js.map +1 -0
  155. package/dist/components/score-ring.d.ts +14 -0
  156. package/dist/components/score-ring.js +79 -0
  157. package/dist/components/score-ring.js.map +1 -0
  158. package/dist/components/scroll-area.d.ts +7 -0
  159. package/dist/components/scroll-area.js +101 -0
  160. package/dist/components/scroll-area.js.map +1 -0
  161. package/dist/components/select.d.ts +17 -0
  162. package/dist/components/select.js +228 -0
  163. package/dist/components/select.js.map +1 -0
  164. package/dist/components/separator.d.ts +6 -0
  165. package/dist/components/separator.js +61 -0
  166. package/dist/components/separator.js.map +1 -0
  167. package/dist/components/sheet.d.ts +16 -0
  168. package/dist/components/sheet.js +168 -0
  169. package/dist/components/sheet.js.map +1 -0
  170. package/dist/components/sidebar.d.ts +73 -0
  171. package/dist/components/sidebar.js +723 -0
  172. package/dist/components/sidebar.js.map +1 -0
  173. package/dist/components/signal-feedback-inline.d.ts +51 -0
  174. package/dist/components/signal-feedback-inline.js +548 -0
  175. package/dist/components/signal-feedback-inline.js.map +1 -0
  176. package/dist/components/simple-data-table.d.ts +15 -0
  177. package/dist/components/simple-data-table.js +91 -0
  178. package/dist/components/simple-data-table.js.map +1 -0
  179. package/dist/components/skeleton.d.ts +5 -0
  180. package/dist/components/skeleton.js +44 -0
  181. package/dist/components/skeleton.js.map +1 -0
  182. package/dist/components/status-badge.d.ts +10 -0
  183. package/dist/components/status-badge.js +82 -0
  184. package/dist/components/status-badge.js.map +1 -0
  185. package/dist/components/styled-bar-list.d.ts +20 -0
  186. package/dist/components/styled-bar-list.js +59 -0
  187. package/dist/components/styled-bar-list.js.map +1 -0
  188. package/dist/components/suggested-actions.d.ts +110 -0
  189. package/dist/components/suggested-actions.js +1538 -0
  190. package/dist/components/suggested-actions.js.map +1 -0
  191. package/dist/components/table.d.ts +12 -0
  192. package/dist/components/table.js +147 -0
  193. package/dist/components/table.js.map +1 -0
  194. package/dist/components/tabs.d.ts +14 -0
  195. package/dist/components/tabs.js +129 -0
  196. package/dist/components/tabs.js.map +1 -0
  197. package/dist/components/textarea.d.ts +5 -0
  198. package/dist/components/textarea.js +47 -0
  199. package/dist/components/textarea.js.map +1 -0
  200. package/dist/components/timeline-activity.d.ts +34 -0
  201. package/dist/components/timeline-activity.js +181 -0
  202. package/dist/components/timeline-activity.js.map +1 -0
  203. package/dist/components/tooltip.d.ts +9 -0
  204. package/dist/components/tooltip.js +93 -0
  205. package/dist/components/tooltip.js.map +1 -0
  206. package/dist/components/view-mode-toggle.d.ts +16 -0
  207. package/dist/components/view-mode-toggle.js +24 -0
  208. package/dist/components/view-mode-toggle.js.map +1 -0
  209. package/dist/hooks/use-mobile.d.ts +3 -0
  210. package/dist/hooks/use-mobile.js +21 -0
  211. package/dist/hooks/use-mobile.js.map +1 -0
  212. package/dist/index.d.ts +68 -1878
  213. package/dist/index.js +69 -10918
  214. package/dist/index.js.map +1 -1
  215. package/dist/lib/icons.d.ts +18 -0
  216. package/dist/lib/icons.js +21 -0
  217. package/dist/lib/icons.js.map +1 -0
  218. package/dist/lib/utils.d.ts +5 -0
  219. package/dist/lib/utils.js +9 -0
  220. package/dist/lib/utils.js.map +1 -0
  221. package/dist/prototype/index.d.ts +20 -0
  222. package/dist/prototype/index.js +8 -0
  223. package/dist/prototype/index.js.map +1 -0
  224. package/dist/prototype/prototype-accounts-view.d.ts +22 -0
  225. package/dist/prototype/prototype-accounts-view.js +70 -0
  226. package/dist/prototype/prototype-accounts-view.js.map +1 -0
  227. package/dist/prototype/prototype-admin-view.d.ts +21 -0
  228. package/dist/prototype/prototype-admin-view.js +53 -0
  229. package/dist/prototype/prototype-admin-view.js.map +1 -0
  230. package/dist/prototype/prototype-config.d.ts +226 -0
  231. package/dist/prototype/prototype-config.js +1 -0
  232. package/dist/prototype/prototype-config.js.map +1 -0
  233. package/dist/prototype/prototype-inbox-view.d.ts +48 -0
  234. package/dist/prototype/prototype-inbox-view.js +701 -0
  235. package/dist/prototype/prototype-inbox-view.js.map +1 -0
  236. package/dist/prototype/prototype-insights-view.d.ts +23 -0
  237. package/dist/prototype/prototype-insights-view.js +335 -0
  238. package/dist/prototype/prototype-insights-view.js.map +1 -0
  239. package/dist/prototype/prototype-shell.d.ts +40 -0
  240. package/dist/prototype/prototype-shell.js +190 -0
  241. package/dist/prototype/prototype-shell.js.map +1 -0
  242. package/dist/prototype/prototype-work-queue-view.d.ts +8 -0
  243. package/dist/prototype/prototype-work-queue-view.js +17 -0
  244. package/dist/prototype/prototype-work-queue-view.js.map +1 -0
  245. package/dist/three/agent-orb.d.ts +39 -0
  246. package/dist/three/agent-orb.js +500 -0
  247. package/dist/three/agent-orb.js.map +1 -0
  248. package/dist/three/index.d.ts +2 -0
  249. package/dist/three/index.js +2 -0
  250. package/dist/three/index.js.map +1 -0
  251. package/package.json +98 -17
  252. package/src/charts/bar-chart-component.tsx +150 -0
  253. package/src/charts/chart-tooltip.tsx +86 -0
  254. package/src/charts/chart.tsx +371 -0
  255. package/src/charts/donut-chart.tsx +112 -0
  256. package/src/charts/index.ts +13 -0
  257. package/src/charts/pipeline-overview.tsx +476 -0
  258. package/src/charts/sankey-chart.tsx +290 -0
  259. package/src/charts/top-line-metrics.tsx +261 -0
  260. package/src/charts/trend-area-chart.tsx +150 -0
  261. package/src/charts/volume-analysis-chart.tsx +124 -0
  262. package/src/components/activity-detail.tsx +233 -0
  263. package/src/components/activity-log.tsx +89 -0
  264. package/src/components/agent-popover.tsx +373 -0
  265. package/src/components/agent-widget.tsx +163 -0
  266. package/src/components/avatar.tsx +109 -0
  267. package/src/components/badge.tsx +48 -0
  268. package/src/components/button.tsx +59 -0
  269. package/src/components/card.tsx +92 -0
  270. package/src/components/contact-list.tsx +121 -0
  271. package/src/components/dashboard-cards.tsx +170 -0
  272. package/src/components/data-table-display.tsx +139 -0
  273. package/src/components/data-table-filter.tsx +138 -0
  274. package/src/components/data-table-quick-views.tsx +103 -0
  275. package/src/components/data-table-toolbar.tsx +56 -0
  276. package/src/components/data-table.tsx +915 -0
  277. package/src/components/detail-view.tsx +237 -0
  278. package/src/components/dialog.tsx +158 -0
  279. package/src/components/dropdown-menu.tsx +257 -0
  280. package/src/components/entity-panel.tsx +767 -0
  281. package/src/components/inbox-row.tsx +132 -0
  282. package/src/components/inbox-toolbar.tsx +213 -0
  283. package/src/components/input.tsx +21 -0
  284. package/src/components/insights-filter-bar.tsx +132 -0
  285. package/src/components/item-list-display.tsx +278 -0
  286. package/src/components/item-list-filter.tsx +118 -0
  287. package/src/components/item-list-toolbar.tsx +97 -0
  288. package/src/components/item-list.tsx +843 -0
  289. package/src/components/label.tsx +24 -0
  290. package/src/components/message.tsx +83 -0
  291. package/src/components/metric-card.tsx +178 -0
  292. package/src/components/performance-metrics-table.tsx +442 -0
  293. package/src/components/preview-list.tsx +62 -0
  294. package/src/components/progress.tsx +31 -0
  295. package/src/components/quick-action-chat-area.tsx +156 -0
  296. package/src/components/quick-action-modal.tsx +331 -0
  297. package/src/components/quick-action-sidebar-nav.tsx +592 -0
  298. package/src/components/recommended-actions-section.tsx +258 -0
  299. package/src/components/report-card.tsx +106 -0
  300. package/src/components/score-analysis-modal.tsx +172 -0
  301. package/src/components/score-breakdown.tsx +179 -0
  302. package/src/components/score-feedback.tsx +288 -0
  303. package/src/components/score-ring.tsx +87 -0
  304. package/src/components/scroll-area.tsx +58 -0
  305. package/src/components/select.tsx +190 -0
  306. package/src/components/separator.tsx +28 -0
  307. package/src/components/sheet.tsx +143 -0
  308. package/src/components/sidebar.tsx +726 -0
  309. package/src/components/signal-feedback-inline.tsx +591 -0
  310. package/src/components/simple-data-table.tsx +124 -0
  311. package/src/components/skeleton.tsx +15 -0
  312. package/src/components/status-badge.tsx +63 -0
  313. package/src/components/styled-bar-list.tsx +70 -0
  314. package/src/components/suggested-actions.tsx +1985 -0
  315. package/src/components/table.tsx +116 -0
  316. package/src/components/tabs.tsx +91 -0
  317. package/src/components/textarea.tsx +18 -0
  318. package/src/components/timeline-activity.tsx +234 -0
  319. package/src/components/tooltip.tsx +57 -0
  320. package/src/components/view-mode-toggle.tsx +39 -0
  321. package/src/hooks/use-mobile.ts +21 -0
  322. package/src/index.ts +77 -0
  323. package/src/lib/icons.ts +18 -0
  324. package/src/lib/utils.ts +6 -0
  325. package/src/prototype/index.ts +11 -0
  326. package/src/prototype/prototype-accounts-view.tsx +112 -0
  327. package/src/prototype/prototype-admin-view.tsx +67 -0
  328. package/src/prototype/prototype-config.ts +243 -0
  329. package/src/prototype/prototype-inbox-view.tsx +810 -0
  330. package/src/prototype/prototype-insights-view.tsx +379 -0
  331. package/src/prototype/prototype-shell.tsx +219 -0
  332. package/src/prototype/prototype-work-queue-view.tsx +30 -0
  333. package/src/styles/globals.css +299 -0
  334. package/src/three/agent-orb.tsx +557 -0
  335. package/src/three/index.ts +5 -0
  336. package/src/types/r3f.d.ts +8 -0
@@ -0,0 +1,592 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ Activity,
6
+ BarChart2,
7
+ Building,
8
+ ChevronDown,
9
+ Code,
10
+ Inbox,
11
+ Link as LinkIcon,
12
+ LogOut,
13
+ MessageSquare,
14
+ MoreHorizontal,
15
+ MoreVertical,
16
+ PanelLeftClose,
17
+ PanelLeftOpen,
18
+ Plus,
19
+ Search,
20
+ Settings,
21
+ Users,
22
+ } from "lucide-react"
23
+
24
+ import { cn } from "../lib/utils"
25
+ import { Avatar, AvatarFallback } from "./avatar"
26
+ import {
27
+ DropdownMenu,
28
+ DropdownMenuContent,
29
+ DropdownMenuItem,
30
+ DropdownMenuLabel,
31
+ DropdownMenuSeparator,
32
+ DropdownMenuTrigger,
33
+ } from "./dropdown-menu"
34
+ import {
35
+ Tooltip,
36
+ TooltipContent,
37
+ TooltipProvider,
38
+ TooltipTrigger,
39
+ } from "./tooltip"
40
+ import { QuickActionModal, type QuickActionTaskDraft, type QuickActionTemplate } from "./quick-action-modal"
41
+
42
+ export interface SidebarNavItem {
43
+ id: string
44
+ label: string
45
+ icon: React.ComponentType<{ className?: string }>
46
+ children?: SidebarNavItem[]
47
+ }
48
+
49
+ export interface SidebarNavSection {
50
+ title?: string
51
+ items: SidebarNavItem[]
52
+ moreItems?: SidebarNavItem[]
53
+ }
54
+
55
+ export interface SidebarUserProfile {
56
+ name: string
57
+ email: string
58
+ initials?: string
59
+ }
60
+
61
+ export interface UserMenuItem {
62
+ id: string
63
+ label: string
64
+ icon: React.ComponentType<{ className?: string }>
65
+ destructive?: boolean
66
+ }
67
+
68
+ export type ActiveVariant = "default" | "gradient"
69
+
70
+ interface QuickActionSidebarNavProps extends React.ComponentProps<"aside"> {
71
+ brandLabel?: string
72
+ brandSubtitle?: string
73
+ brandImage?: string
74
+ hideQuickAction?: boolean
75
+ navSections?: SidebarNavSection[]
76
+ activeItemId?: string
77
+ activeVariant?: ActiveVariant
78
+ onNavigate?: (itemId: string) => void
79
+ user?: SidebarUserProfile
80
+ userMenuItems?: UserMenuItem[]
81
+ onUserMenuAction?: (itemId: string) => void
82
+ onCreateTask?: (draft: QuickActionTaskDraft) => void
83
+ defaultCollapsed?: boolean
84
+ quickActionTemplates?: QuickActionTemplate[]
85
+ quickActionTitle?: string
86
+ quickActionDescription?: string
87
+ }
88
+
89
+ const DEFAULT_NAV_SECTIONS: SidebarNavSection[] = [
90
+ {
91
+ items: [
92
+ { id: "home", label: "Home", icon: Inbox },
93
+ { id: "inbox", label: "Inbox", icon: Inbox },
94
+ ],
95
+ },
96
+ {
97
+ title: "Focus",
98
+ items: [
99
+ { id: "inbox", label: "Unibox", icon: Inbox },
100
+ { id: "accounts", label: "My Accounts", icon: Building },
101
+ { id: "activity", label: "Activity", icon: Activity },
102
+ { id: "dashboard", label: "Insights", icon: BarChart2 },
103
+ ],
104
+ moreItems: [
105
+ { id: "search", label: "Search", icon: Search },
106
+ ],
107
+ },
108
+ {
109
+ title: "Assistant",
110
+ items: [
111
+ { id: "new-chat", label: "New chat", icon: Plus },
112
+ { id: "chats", label: "Chats", icon: MessageSquare },
113
+ ],
114
+ },
115
+ {
116
+ title: "Your Teams",
117
+ items: [
118
+ { id: "team-a", label: "Team A", icon: Users },
119
+ { id: "team-b", label: "Team B", icon: Users },
120
+ ],
121
+ moreItems: [
122
+ { id: "more-teams", label: "More", icon: MoreHorizontal },
123
+ ],
124
+ },
125
+ ]
126
+
127
+ const DEFAULT_USER: SidebarUserProfile = {
128
+ name: "John Doe",
129
+ email: "jdoe@acmeco.com",
130
+ initials: "JD",
131
+ }
132
+
133
+ const DEFAULT_USER_MENU: UserMenuItem[] = [
134
+ { id: "settings", label: "Settings", icon: Settings },
135
+ { id: "dev", label: "Dev", icon: Code },
136
+ { id: "integrations", label: "Integrations", icon: LinkIcon },
137
+ { id: "sign-out", label: "Sign out", icon: LogOut, destructive: true },
138
+ ]
139
+
140
+ function NavItemRow({
141
+ item,
142
+ isActive,
143
+ isCollapsed,
144
+ activeVariant = "default",
145
+ onClick,
146
+ onNavigate,
147
+ activeItemId,
148
+ expandedItems,
149
+ onToggleExpand,
150
+ depth = 0,
151
+ }: {
152
+ item: SidebarNavItem
153
+ isActive: boolean
154
+ isCollapsed: boolean
155
+ activeVariant?: ActiveVariant
156
+ onClick?: () => void
157
+ onNavigate?: (id: string) => void
158
+ activeItemId?: string
159
+ expandedItems?: Record<string, boolean>
160
+ onToggleExpand?: (itemId: string) => void
161
+ depth?: number
162
+ }) {
163
+ const activeClasses =
164
+ activeVariant === "gradient"
165
+ ? "bg-gradient-to-r from-primary/10 to-transparent text-primary"
166
+ : "bg-sidebar-accent text-sidebar-accent-foreground"
167
+
168
+ const iconActiveClasses =
169
+ activeVariant === "gradient" ? "text-primary" : ""
170
+
171
+ const hasChildren = item.children && item.children.length > 0
172
+ const isExpanded = expandedItems?.[item.id] ?? false
173
+
174
+ const content = (
175
+ <div>
176
+ <div className="flex items-center">
177
+ <button
178
+ type="button"
179
+ onClick={onClick}
180
+ className={cn(
181
+ "flex flex-1 items-center gap-3 rounded-lg text-sm font-medium transition-colors",
182
+ isCollapsed ? "justify-center p-2" : "px-3 py-2",
183
+ isActive
184
+ ? activeClasses
185
+ : "text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent",
186
+ )}
187
+ style={depth > 0 && !isCollapsed ? { paddingLeft: `${0.75 + depth * 1}rem` } : undefined}
188
+ >
189
+ <item.icon className={cn("shrink-0", isCollapsed ? "w-5 h-5" : "w-4 h-4", isActive && iconActiveClasses)} />
190
+ {!isCollapsed && <span className="flex-1 truncate text-left">{item.label}</span>}
191
+ </button>
192
+ {hasChildren && !isCollapsed && (
193
+ <button
194
+ type="button"
195
+ onClick={(e) => {
196
+ e.stopPropagation()
197
+ onToggleExpand?.(item.id)
198
+ }}
199
+ className="p-1 mr-1 rounded text-sidebar-foreground/40 hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors"
200
+ >
201
+ <ChevronDown
202
+ className={cn(
203
+ "w-3.5 h-3.5 transition-transform duration-200",
204
+ !isExpanded && "-rotate-90",
205
+ )}
206
+ />
207
+ </button>
208
+ )}
209
+ </div>
210
+ {hasChildren && !isCollapsed && isExpanded && (
211
+ <div className="space-y-0.5">
212
+ {item.children!.map((child) => (
213
+ <NavItemRow
214
+ key={child.id}
215
+ item={child}
216
+ isActive={activeItemId === child.id}
217
+ isCollapsed={isCollapsed}
218
+ activeVariant={activeVariant}
219
+ activeItemId={activeItemId}
220
+ onClick={() => onNavigate?.(child.id)}
221
+ onNavigate={onNavigate}
222
+ expandedItems={expandedItems}
223
+ onToggleExpand={onToggleExpand}
224
+ depth={depth + 1}
225
+ />
226
+ ))}
227
+ </div>
228
+ )}
229
+ </div>
230
+ )
231
+
232
+ if (isCollapsed) {
233
+ return (
234
+ <Tooltip>
235
+ <TooltipTrigger asChild>
236
+ <button
237
+ type="button"
238
+ onClick={onClick}
239
+ className={cn(
240
+ "flex w-full items-center gap-3 rounded-lg text-sm font-medium transition-colors",
241
+ "justify-center p-2",
242
+ isActive
243
+ ? activeClasses
244
+ : "text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent",
245
+ )}
246
+ >
247
+ <item.icon className={cn("shrink-0 w-5 h-5", isActive && iconActiveClasses)} />
248
+ </button>
249
+ </TooltipTrigger>
250
+ <TooltipContent side="right">{item.label}</TooltipContent>
251
+ </Tooltip>
252
+ )
253
+ }
254
+
255
+ return content
256
+ }
257
+
258
+ function NavSection({
259
+ section,
260
+ activeItemId,
261
+ isCollapsed,
262
+ activeVariant = "default",
263
+ onNavigate,
264
+ }: {
265
+ section: SidebarNavSection
266
+ activeItemId?: string
267
+ isCollapsed: boolean
268
+ activeVariant?: ActiveVariant
269
+ onNavigate?: (id: string) => void
270
+ }) {
271
+ const [isExpanded, setIsExpanded] = React.useState(true)
272
+ const [expandedItems, setExpandedItems] = React.useState<Record<string, boolean>>({})
273
+ const hasTitle = !isCollapsed && section.title
274
+
275
+ const handleToggleExpand = React.useCallback((itemId: string) => {
276
+ setExpandedItems((prev) => ({ ...prev, [itemId]: !prev[itemId] }))
277
+ }, [])
278
+
279
+ return (
280
+ <div className="px-3 py-2">
281
+ {hasTitle && (
282
+ <button
283
+ type="button"
284
+ onClick={() => setIsExpanded(!isExpanded)}
285
+ className="flex w-full items-center justify-between mb-1 px-3 group cursor-pointer"
286
+ >
287
+ <span className="text-xs font-bold tracking-widest text-sidebar-foreground/50 uppercase">
288
+ {section.title}
289
+ </span>
290
+ <ChevronDown
291
+ className={cn(
292
+ "w-3 h-3 text-sidebar-foreground/40 transition-transform duration-200",
293
+ !isExpanded && "-rotate-90",
294
+ )}
295
+ />
296
+ </button>
297
+ )}
298
+ {(isExpanded || isCollapsed || !section.title) && (
299
+ <div className="space-y-0.5">
300
+ {section.items.map((item) => (
301
+ <NavItemRow
302
+ key={item.id}
303
+ item={item}
304
+ isActive={activeItemId === item.id}
305
+ isCollapsed={isCollapsed}
306
+ activeVariant={activeVariant}
307
+ activeItemId={activeItemId}
308
+ onClick={() => onNavigate?.(item.id)}
309
+ onNavigate={onNavigate}
310
+ expandedItems={expandedItems}
311
+ onToggleExpand={handleToggleExpand}
312
+ />
313
+ ))}
314
+ {!isCollapsed && section.moreItems && section.moreItems.length > 0 && (
315
+ <DropdownMenu>
316
+ <DropdownMenuTrigger className="flex items-center gap-3 w-full px-3 py-2 rounded-lg text-sm font-medium text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors outline-none">
317
+ <MoreHorizontal className="shrink-0 w-4 h-4" />
318
+ <span className="flex-1 text-left">More</span>
319
+ </DropdownMenuTrigger>
320
+ <DropdownMenuContent align="start" side="bottom" className="w-48">
321
+ {section.moreItems.map((item) => (
322
+ <DropdownMenuItem
323
+ key={item.id}
324
+ onClick={() => onNavigate?.(item.id)}
325
+ className="cursor-pointer"
326
+ >
327
+ <item.icon className="mr-2 w-4 h-4 text-muted-foreground" />
328
+ <span>{item.label}</span>
329
+ </DropdownMenuItem>
330
+ ))}
331
+ </DropdownMenuContent>
332
+ </DropdownMenu>
333
+ )}
334
+ {isCollapsed &&
335
+ section.moreItems?.map((item) => (
336
+ <NavItemRow
337
+ key={item.id}
338
+ item={item}
339
+ isActive={activeItemId === item.id}
340
+ isCollapsed={isCollapsed}
341
+ activeVariant={activeVariant}
342
+ onClick={() => onNavigate?.(item.id)}
343
+ />
344
+ ))}
345
+ </div>
346
+ )}
347
+ </div>
348
+ )
349
+ }
350
+
351
+ export function QuickActionSidebarNav({
352
+ className,
353
+ brandLabel = "ACME CO",
354
+ brandSubtitle = "Placeholder",
355
+ brandImage,
356
+ hideQuickAction,
357
+ navSections = DEFAULT_NAV_SECTIONS,
358
+ activeItemId = "inbox",
359
+ activeVariant = "default",
360
+ onNavigate,
361
+ user = DEFAULT_USER,
362
+ userMenuItems = DEFAULT_USER_MENU,
363
+ onUserMenuAction,
364
+ onCreateTask,
365
+ defaultCollapsed = false,
366
+ quickActionTemplates,
367
+ quickActionTitle,
368
+ quickActionDescription,
369
+ ...props
370
+ }: QuickActionSidebarNavProps) {
371
+ const [isQuickActionOpen, setIsQuickActionOpen] = React.useState(false)
372
+ const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed)
373
+
374
+ const initials =
375
+ user.initials ??
376
+ (user.name
377
+ ? user.name.charAt(0).toUpperCase()
378
+ : user.email
379
+ ? user.email.charAt(0).toUpperCase()
380
+ : "U")
381
+
382
+ return (
383
+ <TooltipProvider delayDuration={0}>
384
+ <aside
385
+ className={cn(
386
+ "flex h-full flex-col overflow-hidden bg-sidebar text-sidebar-foreground border-r border-sidebar-border transition-all duration-200",
387
+ isCollapsed ? "w-16" : "w-64",
388
+ className,
389
+ )}
390
+ {...props}
391
+ >
392
+ {/* Header */}
393
+ <div
394
+ className={cn(
395
+ "relative flex shrink-0 items-center border-b border-sidebar-border",
396
+ isCollapsed ? "justify-center h-16 px-2" : "px-6 py-4",
397
+ )}
398
+ >
399
+ {!isCollapsed && (
400
+ <div className="flex items-center gap-2.5 pr-8">
401
+ {brandImage ? (
402
+ <img src={brandImage} alt={brandLabel} className="h-10 object-contain" />
403
+ ) : (
404
+ <>
405
+ <div className="flex h-6 w-6 items-center justify-center rounded-full bg-sidebar-foreground text-sidebar">
406
+ <svg viewBox="0 0 24 24" fill="currentColor" className="w-3.5 h-3.5">
407
+ <circle cx="12" cy="12" r="10" />
408
+ </svg>
409
+ </div>
410
+ <div className="flex flex-col gap-0.5">
411
+ <span className="text-sm font-bold tracking-tight">
412
+ {brandLabel}
413
+ </span>
414
+ {brandSubtitle && (
415
+ <span className="text-[10px] font-medium text-sidebar-foreground/50 uppercase tracking-wide">
416
+ {brandSubtitle}
417
+ </span>
418
+ )}
419
+ </div>
420
+ </>
421
+ )}
422
+ </div>
423
+ )}
424
+
425
+ <button
426
+ type="button"
427
+ onClick={() => setIsCollapsed(!isCollapsed)}
428
+ className={cn(
429
+ "p-1.5 rounded-md text-sidebar-foreground/50 hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors",
430
+ isCollapsed ? "" : "absolute right-5 top-1/2 -translate-y-1/2",
431
+ )}
432
+ title={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
433
+ >
434
+ {isCollapsed ? (
435
+ <PanelLeftOpen className="w-4 h-4" />
436
+ ) : (
437
+ <PanelLeftClose className="w-4 h-4" />
438
+ )}
439
+ </button>
440
+ </div>
441
+
442
+ {/* Navigation */}
443
+ <div className="flex-1 overflow-y-auto overflow-x-hidden py-3 space-y-1">
444
+ {navSections.map((section, idx) => (
445
+ <React.Fragment key={section.title ?? idx}>
446
+ {idx > 0 && <div className="mx-4 my-2 border-t border-sidebar-border" />}
447
+ <NavSection
448
+ section={section}
449
+ activeItemId={activeItemId}
450
+ isCollapsed={isCollapsed}
451
+ activeVariant={activeVariant}
452
+ onNavigate={onNavigate}
453
+ />
454
+ </React.Fragment>
455
+ ))}
456
+ </div>
457
+
458
+ {!hideQuickAction && (
459
+ <div className={cn("px-3 pb-3", isCollapsed ? "hidden" : "block")}>
460
+ <button
461
+ type="button"
462
+ onClick={() => setIsQuickActionOpen(true)}
463
+ className="w-full flex items-center justify-between px-3 py-2.5 rounded-lg border border-sidebar-border bg-sidebar-primary text-sidebar-primary-foreground hover:bg-sidebar-primary/90 transition-colors group shadow-sm"
464
+ >
465
+ <div className="flex items-center gap-2">
466
+ <svg
467
+ className="w-4 h-4 text-sidebar-primary-foreground/80 group-hover:text-sidebar-primary-foreground transition-colors"
468
+ fill="none"
469
+ stroke="currentColor"
470
+ viewBox="0 0 24 24"
471
+ >
472
+ <path
473
+ strokeLinecap="round"
474
+ strokeLinejoin="round"
475
+ strokeWidth={2}
476
+ d="M13 10V3L4 14h7v7l9-11h-7z"
477
+ />
478
+ </svg>
479
+ <span className="text-sm font-medium">Quick Action</span>
480
+ </div>
481
+ <kbd className="hidden sm:inline-flex items-center gap-0.5 px-1.5 py-0.5 text-[11px] font-mono rounded bg-sidebar-primary-foreground/20 text-sidebar-primary-foreground">
482
+ <span className="text-xs">&#8984;</span>K
483
+ </kbd>
484
+ </button>
485
+ </div>
486
+ )}
487
+
488
+ {isCollapsed && !hideQuickAction && (
489
+ <div className="px-2 pb-3">
490
+ <Tooltip>
491
+ <TooltipTrigger asChild>
492
+ <button
493
+ type="button"
494
+ onClick={() => setIsQuickActionOpen(true)}
495
+ className="flex w-full items-center justify-center rounded-lg bg-sidebar-primary p-2.5 text-sidebar-primary-foreground shadow-sm transition-colors hover:bg-sidebar-primary/90"
496
+ title="Quick Action (⌘K)"
497
+ >
498
+ <svg
499
+ className="w-5 h-5"
500
+ fill="none"
501
+ stroke="currentColor"
502
+ viewBox="0 0 24 24"
503
+ >
504
+ <path
505
+ strokeLinecap="round"
506
+ strokeLinejoin="round"
507
+ strokeWidth={2}
508
+ d="M13 10V3L4 14h7v7l9-11h-7z"
509
+ />
510
+ </svg>
511
+ </button>
512
+ </TooltipTrigger>
513
+ <TooltipContent side="right">Quick Action (⌘K)</TooltipContent>
514
+ </Tooltip>
515
+ </div>
516
+ )}
517
+
518
+ {/* User Profile Footer */}
519
+ <div className="p-3 border-t border-sidebar-border shrink-0">
520
+ <DropdownMenu>
521
+ <DropdownMenuTrigger
522
+ className={cn(
523
+ "flex items-center w-full rounded-lg hover:bg-sidebar-accent transition-colors outline-none",
524
+ isCollapsed ? "justify-center p-1" : "p-2 gap-3",
525
+ )}
526
+ >
527
+ <Avatar className="h-8 w-8 rounded-md">
528
+ <AvatarFallback className="rounded-md bg-primary/10 text-primary text-xs font-medium">
529
+ {initials}
530
+ </AvatarFallback>
531
+ </Avatar>
532
+
533
+ {!isCollapsed && (
534
+ <div className="flex flex-col items-start flex-1 truncate">
535
+ <span className="text-sm font-medium leading-none truncate">
536
+ {user.name}
537
+ </span>
538
+ <span className="text-xs text-sidebar-foreground/50 truncate mt-0.5">
539
+ {user.email}
540
+ </span>
541
+ </div>
542
+ )}
543
+
544
+ {!isCollapsed && (
545
+ <MoreVertical className="w-4 h-4 text-sidebar-foreground/50 shrink-0" />
546
+ )}
547
+ </DropdownMenuTrigger>
548
+
549
+ <DropdownMenuContent align="end" side="right" sideOffset={8} className="w-56">
550
+ <DropdownMenuLabel className="font-normal">
551
+ <div className="flex flex-col space-y-1">
552
+ <p className="text-sm font-medium leading-none">{user.name}</p>
553
+ <p className="text-xs leading-none text-muted-foreground">{user.email}</p>
554
+ </div>
555
+ </DropdownMenuLabel>
556
+ <DropdownMenuSeparator />
557
+ {userMenuItems.map((item, idx) => {
558
+ const showSepBefore = item.destructive && idx > 0
559
+ return (
560
+ <React.Fragment key={item.id}>
561
+ {showSepBefore && <DropdownMenuSeparator />}
562
+ <DropdownMenuItem
563
+ onClick={() => onUserMenuAction?.(item.id)}
564
+ className={cn(
565
+ "cursor-pointer",
566
+ item.destructive && "text-destructive focus:text-destructive",
567
+ )}
568
+ >
569
+ <item.icon className="mr-2 h-4 w-4" />
570
+ <span>{item.label}</span>
571
+ </DropdownMenuItem>
572
+ </React.Fragment>
573
+ )
574
+ })}
575
+ </DropdownMenuContent>
576
+ </DropdownMenu>
577
+ </div>
578
+ </aside>
579
+
580
+ {!hideQuickAction && (
581
+ <QuickActionModal
582
+ open={isQuickActionOpen}
583
+ onOpenChange={setIsQuickActionOpen}
584
+ onCreateTask={onCreateTask}
585
+ templates={quickActionTemplates}
586
+ title={quickActionTitle}
587
+ description={quickActionDescription}
588
+ />
589
+ )}
590
+ </TooltipProvider>
591
+ )
592
+ }