ai-design-system 0.1.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 (290) hide show
  1. package/README.md +307 -0
  2. package/components/ai-elements/actions.tsx +65 -0
  3. package/components/ai-elements/artifact.tsx +147 -0
  4. package/components/ai-elements/branch.tsx +212 -0
  5. package/components/ai-elements/canvas.tsx +24 -0
  6. package/components/ai-elements/chain-of-thought.tsx +228 -0
  7. package/components/ai-elements/code-block.tsx +179 -0
  8. package/components/ai-elements/confirmation.tsx +169 -0
  9. package/components/ai-elements/connection.tsx +28 -0
  10. package/components/ai-elements/context.tsx +408 -0
  11. package/components/ai-elements/controls.tsx +18 -0
  12. package/components/ai-elements/conversation.tsx +97 -0
  13. package/components/ai-elements/edge.tsx +140 -0
  14. package/components/ai-elements/image.tsx +24 -0
  15. package/components/ai-elements/inline-citation.tsx +287 -0
  16. package/components/ai-elements/loader.tsx +96 -0
  17. package/components/ai-elements/message.tsx +80 -0
  18. package/components/ai-elements/node.tsx +71 -0
  19. package/components/ai-elements/open-in-chat.tsx +363 -0
  20. package/components/ai-elements/panel.tsx +15 -0
  21. package/components/ai-elements/plan.tsx +142 -0
  22. package/components/ai-elements/prompt-input.tsx +1352 -0
  23. package/components/ai-elements/queue.tsx +274 -0
  24. package/components/ai-elements/reasoning.tsx +178 -0
  25. package/components/ai-elements/response.tsx +22 -0
  26. package/components/ai-elements/shimmer.tsx +64 -0
  27. package/components/ai-elements/sources.tsx +77 -0
  28. package/components/ai-elements/suggestion.tsx +56 -0
  29. package/components/ai-elements/task.tsx +87 -0
  30. package/components/ai-elements/tool.tsx +179 -0
  31. package/components/ai-elements/toolbar.tsx +16 -0
  32. package/components/ai-elements/web-preview.tsx +263 -0
  33. package/components/blocks/AIConversation/AIConversation.stories.tsx +164 -0
  34. package/components/blocks/AIConversation/AIConversation.tsx +186 -0
  35. package/components/blocks/AIConversation/index.ts +8 -0
  36. package/components/blocks/AppSidebar/AppSidebar.stories.tsx +63 -0
  37. package/components/blocks/AppSidebar/AppSidebar.tsx +87 -0
  38. package/components/blocks/AppSidebar/index.ts +2 -0
  39. package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.stories.tsx +341 -0
  40. package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.tsx +255 -0
  41. package/components/blocks/DocumentEditorWithComments/index.ts +9 -0
  42. package/components/blocks/FileChangeQueue/FileChangeQueue.stories.tsx +207 -0
  43. package/components/blocks/FileChangeQueue/FileChangeQueue.tsx +143 -0
  44. package/components/blocks/FileChangeQueue/index.ts +7 -0
  45. package/components/blocks/LayoutProvider/LayoutProvider.tsx +34 -0
  46. package/components/blocks/LayoutProvider/index.ts +1 -0
  47. package/components/blocks/index.ts +2 -0
  48. package/components/composites/AgentIndicator/AgentIndicator.stories.tsx +154 -0
  49. package/components/composites/AgentIndicator/AgentIndicator.tsx +102 -0
  50. package/components/composites/AgentIndicator/index.ts +8 -0
  51. package/components/composites/AppHeader/AppHeader.stories.tsx +46 -0
  52. package/components/composites/AppHeader/AppHeader.tsx +24 -0
  53. package/components/composites/AppHeader/index.ts +2 -0
  54. package/components/composites/CommentBox/CommentBox.stories.tsx +192 -0
  55. package/components/composites/CommentBox/CommentBox.tsx +364 -0
  56. package/components/composites/CommentBox/index.ts +8 -0
  57. package/components/composites/Confirmation/Confirmation.stories.tsx +151 -0
  58. package/components/composites/Confirmation/Confirmation.tsx +93 -0
  59. package/components/composites/Confirmation/index.ts +7 -0
  60. package/components/composites/DataTable/DataTable.stories.tsx +35 -0
  61. package/components/composites/DataTable/DataTable.tsx +95 -0
  62. package/components/composites/DataTable/index.ts +2 -0
  63. package/components/composites/DocumentEditor/DocumentEditor.css +106 -0
  64. package/components/composites/DocumentEditor/DocumentEditor.stories.tsx +927 -0
  65. package/components/composites/DocumentEditor/DocumentEditor.tsx +279 -0
  66. package/components/composites/DocumentEditor/index.ts +8 -0
  67. package/components/composites/FileQueue/FileQueue.stories.tsx +175 -0
  68. package/components/composites/FileQueue/FileQueue.tsx +161 -0
  69. package/components/composites/FileQueue/FileStatusBadge.tsx +74 -0
  70. package/components/composites/FileQueue/index.ts +24 -0
  71. package/components/composites/InteractiveChart/InteractiveChart.stories.tsx +49 -0
  72. package/components/composites/InteractiveChart/InteractiveChart.tsx +69 -0
  73. package/components/composites/InteractiveChart/index.ts +2 -0
  74. package/components/composites/ModeToggle/ModeToggle.stories.tsx +212 -0
  75. package/components/composites/ModeToggle/ModeToggle.tsx +100 -0
  76. package/components/composites/ModeToggle/index.ts +7 -0
  77. package/components/composites/NavUser/NavUser.stories.tsx +50 -0
  78. package/components/composites/NavUser/NavUser.tsx +60 -0
  79. package/components/composites/NavUser/index.ts +2 -0
  80. package/components/composites/NavigationList/NavigationList.stories.tsx +46 -0
  81. package/components/composites/NavigationList/NavigationList.tsx +46 -0
  82. package/components/composites/NavigationList/index.ts +2 -0
  83. package/components/composites/OrchestratorMessage/OrchestratorMessage.stories.tsx +188 -0
  84. package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +72 -0
  85. package/components/composites/OrchestratorMessage/index.ts +8 -0
  86. package/components/composites/PageContainer/PageContainer.stories.tsx +41 -0
  87. package/components/composites/PageContainer/PageContainer.tsx +24 -0
  88. package/components/composites/PageContainer/index.ts +2 -0
  89. package/components/composites/PromptInput/PromptInput.stories.tsx +200 -0
  90. package/components/composites/PromptInput/PromptInput.tsx +129 -0
  91. package/components/composites/PromptInput/index.ts +8 -0
  92. package/components/composites/SpecialistMessage/SpecialistMessage.stories.tsx +286 -0
  93. package/components/composites/SpecialistMessage/SpecialistMessage.tsx +107 -0
  94. package/components/composites/SpecialistMessage/index.ts +8 -0
  95. package/components/composites/StatsCard/StatsCard.stories.tsx +76 -0
  96. package/components/composites/StatsCard/StatsCard.tsx +81 -0
  97. package/components/composites/StatsCard/index.ts +2 -0
  98. package/components/composites/TablePagination/TablePagination.stories.tsx +38 -0
  99. package/components/composites/TablePagination/TablePagination.tsx +119 -0
  100. package/components/composites/TablePagination/index.ts +2 -0
  101. package/components/composites/TableToolbar/TableToolbar.stories.tsx +60 -0
  102. package/components/composites/TableToolbar/TableToolbar.tsx +66 -0
  103. package/components/composites/TableToolbar/index.ts +2 -0
  104. package/components/composites/ThemeSelector/ThemeSelector.stories.tsx +48 -0
  105. package/components/composites/ThemeSelector/ThemeSelector.tsx +79 -0
  106. package/components/composites/ThemeSelector/index.ts +2 -0
  107. package/components/composites/ToolCallDisplay/ToolCallDisplay.stories.tsx +49 -0
  108. package/components/composites/ToolCallDisplay/ToolCallDisplay.tsx +108 -0
  109. package/components/composites/ToolCallDisplay/index.ts +8 -0
  110. package/components/composites/UserMessage/UserMessage.stories.tsx +59 -0
  111. package/components/composites/UserMessage/UserMessage.tsx +52 -0
  112. package/components/composites/UserMessage/index.ts +8 -0
  113. package/components/composites/index.ts +90 -0
  114. package/components/features/AIDocEditor/AIDocEditor.behaviors.stories.tsx +451 -0
  115. package/components/features/AIDocEditor/AIDocEditor.mocks.ts +96 -0
  116. package/components/features/AIDocEditor/AIDocEditor.stories.tsx +140 -0
  117. package/components/features/AIDocEditor/AIDocEditor.tsx +130 -0
  118. package/components/features/AIDocEditor/index.ts +8 -0
  119. package/components/features/AIDocEditor/useAIDocEditor.d.ts +97 -0
  120. package/components/features/AIDocEditor/useAIDocEditor.mock.ts +83 -0
  121. package/components/features/PageLayout/PageLayout.behaviors.stories.tsx +119 -0
  122. package/components/features/PageLayout/PageLayout.mocks.ts +27 -0
  123. package/components/features/PageLayout/PageLayout.stories.tsx +142 -0
  124. package/components/features/PageLayout/PageLayout.tsx +94 -0
  125. package/components/features/PageLayout/index.ts +4 -0
  126. package/components/features/PageLayout/usePageLayout.d.ts +24 -0
  127. package/components/features/PageLayout/usePageLayout.mock.ts +19 -0
  128. package/components/features/RefinementPanel/README.md +189 -0
  129. package/components/features/RefinementPanel/RefinementPanel.behaviors.stories.tsx +475 -0
  130. package/components/features/RefinementPanel/RefinementPanel.mocks.ts +131 -0
  131. package/components/features/RefinementPanel/RefinementPanel.stories.tsx +141 -0
  132. package/components/features/RefinementPanel/RefinementPanel.tsx +160 -0
  133. package/components/features/RefinementPanel/index.ts +25 -0
  134. package/components/features/RefinementPanel/useRefinementPanel.d.ts +74 -0
  135. package/components/features/RefinementPanel/useRefinementPanel.mock.ts +121 -0
  136. package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +379 -0
  137. package/components/features/SpecNavigator/SpecNavigator.mocks.ts +131 -0
  138. package/components/features/SpecNavigator/SpecNavigator.stories.tsx +122 -0
  139. package/components/features/SpecNavigator/SpecNavigator.tsx +43 -0
  140. package/components/features/SpecNavigator/index.ts +2 -0
  141. package/components/features/SpecNavigator/useSpecNavigator.d.ts +122 -0
  142. package/components/features/SpecNavigator/useSpecNavigator.mock.ts +93 -0
  143. package/components/features/index.ts +18 -0
  144. package/components/index.ts +14 -0
  145. package/components/primitives/Accordion/Accordion.stories.tsx +87 -0
  146. package/components/primitives/Accordion/Accordion.tsx +66 -0
  147. package/components/primitives/Accordion/index.ts +13 -0
  148. package/components/primitives/Alert/Alert.stories.tsx +422 -0
  149. package/components/primitives/Alert/Alert.tsx +61 -0
  150. package/components/primitives/Alert/index.ts +8 -0
  151. package/components/primitives/AlertDialog/AlertDialog.stories.tsx +367 -0
  152. package/components/primitives/AlertDialog/AlertDialog.tsx +182 -0
  153. package/components/primitives/AlertDialog/index.ts +25 -0
  154. package/components/primitives/Avatar/Avatar.stories.tsx +321 -0
  155. package/components/primitives/Avatar/Avatar.tsx +63 -0
  156. package/components/primitives/Avatar/index.ts +8 -0
  157. package/components/primitives/Badge/Badge.stories.tsx +74 -0
  158. package/components/primitives/Badge/Badge.tsx +49 -0
  159. package/components/primitives/Badge/index.ts +2 -0
  160. package/components/primitives/Button/Button.stories.tsx +445 -0
  161. package/components/primitives/Button/Button.tsx +89 -0
  162. package/components/primitives/Button/index.ts +7 -0
  163. package/components/primitives/Card/Card.stories.tsx +831 -0
  164. package/components/primitives/Card/Card.tsx +242 -0
  165. package/components/primitives/Card/index.ts +30 -0
  166. package/components/primitives/Carousel/Carousel.stories.tsx +32 -0
  167. package/components/primitives/Carousel/Carousel.tsx +63 -0
  168. package/components/primitives/Carousel/index.ts +13 -0
  169. package/components/primitives/Chart/Chart.stories.tsx +346 -0
  170. package/components/primitives/Chart/Chart.tsx +117 -0
  171. package/components/primitives/Chart/index.ts +20 -0
  172. package/components/primitives/Checkbox/Checkbox.stories.tsx +87 -0
  173. package/components/primitives/Checkbox/Checkbox.tsx +38 -0
  174. package/components/primitives/Checkbox/index.ts +2 -0
  175. package/components/primitives/Collapsible/Collapsible.stories.tsx +38 -0
  176. package/components/primitives/Collapsible/Collapsible.tsx +39 -0
  177. package/components/primitives/Collapsible/index.ts +8 -0
  178. package/components/primitives/Command/Command.stories.tsx +150 -0
  179. package/components/primitives/Command/Command.tsx +147 -0
  180. package/components/primitives/Command/index.ts +20 -0
  181. package/components/primitives/Dialog/Dialog.stories.tsx +390 -0
  182. package/components/primitives/Dialog/Dialog.tsx +140 -0
  183. package/components/primitives/Dialog/index.ts +22 -0
  184. package/components/primitives/Drawer/Drawer.stories.tsx +327 -0
  185. package/components/primitives/Drawer/Drawer.tsx +208 -0
  186. package/components/primitives/Drawer/index.ts +27 -0
  187. package/components/primitives/DropdownMenu/DropdownMenu.stories.tsx +150 -0
  188. package/components/primitives/DropdownMenu/DropdownMenu.tsx +73 -0
  189. package/components/primitives/DropdownMenu/index.ts +1 -0
  190. package/components/primitives/HoverCard/HoverCard.stories.tsx +26 -0
  191. package/components/primitives/HoverCard/HoverCard.tsx +39 -0
  192. package/components/primitives/HoverCard/index.ts +8 -0
  193. package/components/primitives/Icon/Icon.stories.tsx +281 -0
  194. package/components/primitives/Icon/Icon.tsx +87 -0
  195. package/components/primitives/Icon/index.ts +8 -0
  196. package/components/primitives/Input/Input.stories.tsx +370 -0
  197. package/components/primitives/Input/Input.tsx +88 -0
  198. package/components/primitives/Input/index.ts +7 -0
  199. package/components/primitives/InputGroup/InputGroup.stories.tsx +40 -0
  200. package/components/primitives/InputGroup/InputGroup.tsx +72 -0
  201. package/components/primitives/InputGroup/index.ts +14 -0
  202. package/components/primitives/Label/Label.stories.tsx +227 -0
  203. package/components/primitives/Label/Label.tsx +53 -0
  204. package/components/primitives/Label/index.ts +7 -0
  205. package/components/primitives/Popover/Popover.stories.tsx +42 -0
  206. package/components/primitives/Popover/Popover.tsx +107 -0
  207. package/components/primitives/Popover/index.ts +2 -0
  208. package/components/primitives/Progress/Progress.stories.tsx +340 -0
  209. package/components/primitives/Progress/Progress.tsx +31 -0
  210. package/components/primitives/Progress/index.ts +1 -0
  211. package/components/primitives/ScrollArea/ScrollArea.stories.tsx +26 -0
  212. package/components/primitives/ScrollArea/ScrollArea.tsx +28 -0
  213. package/components/primitives/ScrollArea/index.ts +6 -0
  214. package/components/primitives/Select/Select.stories.tsx +288 -0
  215. package/components/primitives/Select/Select.tsx +162 -0
  216. package/components/primitives/Select/index.ts +22 -0
  217. package/components/primitives/Separator/Separator.stories.tsx +264 -0
  218. package/components/primitives/Separator/Separator.tsx +48 -0
  219. package/components/primitives/Separator/index.ts +7 -0
  220. package/components/primitives/Sidebar/Sidebar.stories.tsx +358 -0
  221. package/components/primitives/Sidebar/Sidebar.tsx +317 -0
  222. package/components/primitives/Sidebar/index.ts +41 -0
  223. package/components/primitives/Table/Table.stories.tsx +389 -0
  224. package/components/primitives/Table/Table.tsx +191 -0
  225. package/components/primitives/Table/index.ts +26 -0
  226. package/components/primitives/Tabs/Tabs.stories.tsx +129 -0
  227. package/components/primitives/Tabs/Tabs.tsx +70 -0
  228. package/components/primitives/Tabs/index.ts +13 -0
  229. package/components/primitives/Textarea/Textarea.stories.tsx +358 -0
  230. package/components/primitives/Textarea/Textarea.tsx +91 -0
  231. package/components/primitives/Textarea/index.ts +7 -0
  232. package/components/primitives/ToggleGroup/ToggleGroup.stories.tsx +87 -0
  233. package/components/primitives/ToggleGroup/ToggleGroup.tsx +52 -0
  234. package/components/primitives/ToggleGroup/index.ts +6 -0
  235. package/components/primitives/Tooltip/Tooltip.stories.tsx +336 -0
  236. package/components/primitives/Tooltip/Tooltip.tsx +78 -0
  237. package/components/primitives/Tooltip/index.ts +10 -0
  238. package/components/primitives/index.ts +34 -0
  239. package/components/ui/accordion.tsx +66 -0
  240. package/components/ui/alert-dialog.tsx +157 -0
  241. package/components/ui/alert.tsx +66 -0
  242. package/components/ui/avatar.tsx +53 -0
  243. package/components/ui/badge.tsx +46 -0
  244. package/components/ui/button.tsx +60 -0
  245. package/components/ui/card.tsx +117 -0
  246. package/components/ui/carousel.tsx +241 -0
  247. package/components/ui/chart.tsx +334 -0
  248. package/components/ui/checkbox.tsx +32 -0
  249. package/components/ui/collapsible.tsx +33 -0
  250. package/components/ui/command.tsx +184 -0
  251. package/components/ui/dialog.tsx +143 -0
  252. package/components/ui/drawer.tsx +118 -0
  253. package/components/ui/dropdown-menu.tsx +257 -0
  254. package/components/ui/hover-card.tsx +44 -0
  255. package/components/ui/input-group.tsx +170 -0
  256. package/components/ui/input.tsx +48 -0
  257. package/components/ui/label.tsx +26 -0
  258. package/components/ui/popover.tsx +33 -0
  259. package/components/ui/progress.tsx +31 -0
  260. package/components/ui/scroll-area.tsx +58 -0
  261. package/components/ui/select.tsx +187 -0
  262. package/components/ui/separator.tsx +31 -0
  263. package/components/ui/sidebar.tsx +577 -0
  264. package/components/ui/table.tsx +120 -0
  265. package/components/ui/tabs.tsx +66 -0
  266. package/components/ui/textarea.tsx +46 -0
  267. package/components/ui/toggle-group.tsx +83 -0
  268. package/components/ui/toggle.tsx +47 -0
  269. package/components/ui/tooltip.tsx +61 -0
  270. package/dist/index.cjs +7389 -0
  271. package/dist/index.cjs.map +1 -0
  272. package/dist/index.css +75 -0
  273. package/dist/index.css.map +1 -0
  274. package/dist/index.js +7160 -0
  275. package/dist/index.js.map +1 -0
  276. package/hooks/useAIDocReviewer.d.ts +0 -0
  277. package/lib/utils.ts +6 -0
  278. package/package.json +140 -0
  279. package/tokens/color/base.json +14 -0
  280. package/tokens/color/dark.json +40 -0
  281. package/tokens/color/green.json +21 -0
  282. package/tokens/color/light.json +52 -0
  283. package/tokens/color/neutral.json +20 -0
  284. package/tokens/color/violet.json +21 -0
  285. package/tokens/spacing.json +22 -0
  286. package/utils/ai-editor/format-date.ts +41 -0
  287. package/utils/ai-editor/index.ts +22 -0
  288. package/utils/ai-editor/type-guards.ts +72 -0
  289. package/utils/ai-editor/validation.ts +130 -0
  290. package/utils/editor-annotations.ts +122 -0
@@ -0,0 +1,150 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import {
3
+ Command,
4
+ CommandEmpty,
5
+ CommandGroup,
6
+ CommandInput,
7
+ CommandItem,
8
+ CommandList,
9
+ CommandSeparator,
10
+ CommandShortcut,
11
+ CommandDialog,
12
+ } from "./Command";
13
+ import { useState } from "react";
14
+
15
+ const meta: Meta<typeof Command> = {
16
+ title: "Primitives/Command",
17
+ component: Command,
18
+ parameters: {
19
+ layout: "centered",
20
+ docs: {
21
+ description: {
22
+ component:
23
+ "A command menu component with fuzzy search and keyboard navigation. Perfect for command palettes.",
24
+ },
25
+ },
26
+ },
27
+ tags: ["autodocs"],
28
+ };
29
+
30
+ export default meta;
31
+ type Story = StoryObj<typeof Command>;
32
+
33
+ export const Default: Story = {
34
+ render: () => (
35
+ <Command className="rounded-lg border shadow-md w-[450px]">
36
+ <CommandInput placeholder="Type a command or search..." />
37
+ <CommandList>
38
+ <CommandEmpty>No results found.</CommandEmpty>
39
+ <CommandGroup heading="Suggestions">
40
+ <CommandItem>Calendar</CommandItem>
41
+ <CommandItem>Search Emoji</CommandItem>
42
+ <CommandItem>Calculator</CommandItem>
43
+ </CommandGroup>
44
+ <CommandSeparator />
45
+ <CommandGroup heading="Settings">
46
+ <CommandItem>Profile</CommandItem>
47
+ <CommandItem>Billing</CommandItem>
48
+ <CommandItem>Settings</CommandItem>
49
+ </CommandGroup>
50
+ </CommandList>
51
+ </Command>
52
+ ),
53
+ };
54
+
55
+ export const WithIcons: Story = {
56
+ render: () => (
57
+ <Command className="rounded-lg border shadow-md w-[450px]">
58
+ <CommandInput placeholder="Search..." />
59
+ <CommandList>
60
+ <CommandEmpty>No results found.</CommandEmpty>
61
+ <CommandGroup heading="Actions">
62
+ <CommandItem>
63
+ <svg
64
+ xmlns="http://www.w3.org/2000/svg"
65
+ width="16"
66
+ height="16"
67
+ viewBox="0 0 24 24"
68
+ fill="none"
69
+ stroke="currentColor"
70
+ strokeWidth="2"
71
+ >
72
+ <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" />
73
+ <circle cx="12" cy="7" r="4" />
74
+ </svg>
75
+ <span>Profile</span>
76
+ </CommandItem>
77
+ <CommandItem>
78
+ <svg
79
+ xmlns="http://www.w3.org/2000/svg"
80
+ width="16"
81
+ height="16"
82
+ viewBox="0 0 24 24"
83
+ fill="none"
84
+ stroke="currentColor"
85
+ strokeWidth="2"
86
+ >
87
+ <circle cx="12" cy="12" r="10" />
88
+ <path d="M12 16v-4" />
89
+ <path d="M12 8h.01" />
90
+ </svg>
91
+ <span>Help</span>
92
+ </CommandItem>
93
+ </CommandGroup>
94
+ </CommandList>
95
+ </Command>
96
+ ),
97
+ };
98
+
99
+ export const WithShortcuts: Story = {
100
+ render: () => (
101
+ <Command className="rounded-lg border shadow-md w-[450px]">
102
+ <CommandInput placeholder="Search..." />
103
+ <CommandList>
104
+ <CommandEmpty>No results found.</CommandEmpty>
105
+ <CommandGroup heading="File">
106
+ <CommandItem>
107
+ <span>New File</span>
108
+ <CommandShortcut>⌘N</CommandShortcut>
109
+ </CommandItem>
110
+ <CommandItem>
111
+ <span>Save</span>
112
+ <CommandShortcut>⌘S</CommandShortcut>
113
+ </CommandItem>
114
+ <CommandItem>
115
+ <span>Print</span>
116
+ <CommandShortcut>⌘P</CommandShortcut>
117
+ </CommandItem>
118
+ </CommandGroup>
119
+ </CommandList>
120
+ </Command>
121
+ ),
122
+ };
123
+
124
+ export const AsDialog: Story = {
125
+ render: () => {
126
+ const [open, setOpen] = useState(false);
127
+
128
+ return (
129
+ <>
130
+ <button
131
+ onClick={() => setOpen(true)}
132
+ className="px-4 py-2 bg-primary text-primary-foreground rounded-md"
133
+ >
134
+ Open Command Menu (⌘K)
135
+ </button>
136
+ <CommandDialog open={open} onOpenChange={setOpen}>
137
+ <CommandInput placeholder="Type a command or search..." />
138
+ <CommandList>
139
+ <CommandEmpty>No results found.</CommandEmpty>
140
+ <CommandGroup heading="Suggestions">
141
+ <CommandItem onSelect={() => setOpen(false)}>Calendar</CommandItem>
142
+ <CommandItem onSelect={() => setOpen(false)}>Search Emoji</CommandItem>
143
+ <CommandItem onSelect={() => setOpen(false)}>Calculator</CommandItem>
144
+ </CommandGroup>
145
+ </CommandList>
146
+ </CommandDialog>
147
+ </>
148
+ );
149
+ },
150
+ };
@@ -0,0 +1,147 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import {
5
+ Command as ShadcnCommand,
6
+ CommandDialog as ShadcnCommandDialog,
7
+ CommandEmpty as ShadcnCommandEmpty,
8
+ CommandGroup as ShadcnCommandGroup,
9
+ CommandInput as ShadcnCommandInput,
10
+ CommandItem as ShadcnCommandItem,
11
+ CommandList as ShadcnCommandList,
12
+ CommandSeparator as ShadcnCommandSeparator,
13
+ CommandShortcut as ShadcnCommandShortcut,
14
+ } from "@/components/ui/command";
15
+
16
+ /**
17
+ * Command Primitive
18
+ *
19
+ * A command menu component for search and command palette functionality.
20
+ * Built on cmdk (Command+K) library with full keyboard navigation.
21
+ *
22
+ * Features:
23
+ * - Fast fuzzy search
24
+ * - Keyboard navigation
25
+ * - Command groups and shortcuts
26
+ * - Dialog mode for command palette
27
+ * - Empty state handling
28
+ * - WCAG 2.1 Level AA compliant
29
+ */
30
+
31
+ export type CommandProps = React.ComponentProps<typeof ShadcnCommand>;
32
+ export type CommandDialogProps = React.ComponentProps<typeof ShadcnCommandDialog>;
33
+ export type CommandInputProps = React.ComponentProps<typeof ShadcnCommandInput>;
34
+ export type CommandListProps = React.ComponentProps<typeof ShadcnCommandList>;
35
+ export type CommandEmptyProps = React.ComponentProps<typeof ShadcnCommandEmpty>;
36
+ export type CommandGroupProps = React.ComponentProps<typeof ShadcnCommandGroup>;
37
+ export type CommandItemProps = React.ComponentProps<typeof ShadcnCommandItem>;
38
+ export type CommandSeparatorProps = React.ComponentProps<typeof ShadcnCommandSeparator>;
39
+ export type CommandShortcutProps = React.ComponentProps<typeof ShadcnCommandShortcut>;
40
+
41
+ /**
42
+ * Command - Root command menu component
43
+ */
44
+ export const Command = React.memo<CommandProps>(
45
+ React.forwardRef<React.ElementRef<typeof ShadcnCommand>, CommandProps>(
46
+ (props, ref) => {
47
+ return <ShadcnCommand ref={ref} {...props} />;
48
+ }
49
+ )
50
+ );
51
+ Command.displayName = "Command";
52
+
53
+ /**
54
+ * CommandDialog - Command menu in a dialog (Command+K style)
55
+ */
56
+ export const CommandDialog = React.memo<CommandDialogProps>(
57
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandDialog>, CommandDialogProps>(
58
+ (props, ref) => {
59
+ return <ShadcnCommandDialog {...props} />;
60
+ }
61
+ )
62
+ );
63
+ CommandDialog.displayName = "CommandDialog";
64
+
65
+ /**
66
+ * CommandInput - Search input for filtering commands
67
+ */
68
+ export const CommandInput = React.memo<CommandInputProps>(
69
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandInput>, CommandInputProps>(
70
+ (props, ref) => {
71
+ return <ShadcnCommandInput ref={ref} {...props} />;
72
+ }
73
+ )
74
+ );
75
+ CommandInput.displayName = "CommandInput";
76
+
77
+ /**
78
+ * CommandList - Scrollable list container for command items
79
+ */
80
+ export const CommandList = React.memo<CommandListProps>(
81
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandList>, CommandListProps>(
82
+ (props, ref) => {
83
+ return <ShadcnCommandList ref={ref} {...props} />;
84
+ }
85
+ )
86
+ );
87
+ CommandList.displayName = "CommandList";
88
+
89
+ /**
90
+ * CommandEmpty - Displayed when no results found
91
+ */
92
+ export const CommandEmpty = React.memo<CommandEmptyProps>(
93
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandEmpty>, CommandEmptyProps>(
94
+ (props, ref) => {
95
+ return <ShadcnCommandEmpty ref={ref} {...props} />;
96
+ }
97
+ )
98
+ );
99
+ CommandEmpty.displayName = "CommandEmpty";
100
+
101
+ /**
102
+ * CommandGroup - Groups related command items
103
+ */
104
+ export const CommandGroup = React.memo<CommandGroupProps>(
105
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandGroup>, CommandGroupProps>(
106
+ (props, ref) => {
107
+ return <ShadcnCommandGroup ref={ref} {...props} />;
108
+ }
109
+ )
110
+ );
111
+ CommandGroup.displayName = "CommandGroup";
112
+
113
+ /**
114
+ * CommandItem - Individual command item
115
+ */
116
+ export const CommandItem = React.memo<CommandItemProps>(
117
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandItem>, CommandItemProps>(
118
+ (props, ref) => {
119
+ return <ShadcnCommandItem ref={ref} {...props} />;
120
+ }
121
+ )
122
+ );
123
+ CommandItem.displayName = "CommandItem";
124
+
125
+ /**
126
+ * CommandSeparator - Visual separator between groups
127
+ */
128
+ export const CommandSeparator = React.memo<CommandSeparatorProps>(
129
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandSeparator>, CommandSeparatorProps>(
130
+ (props, ref) => {
131
+ return <ShadcnCommandSeparator ref={ref} {...props} />;
132
+ }
133
+ )
134
+ );
135
+ CommandSeparator.displayName = "CommandSeparator";
136
+
137
+ /**
138
+ * CommandShortcut - Displays keyboard shortcut hint
139
+ */
140
+ export const CommandShortcut = React.memo<CommandShortcutProps>(
141
+ React.forwardRef<React.ElementRef<typeof ShadcnCommandShortcut>, CommandShortcutProps>(
142
+ (props, ref) => {
143
+ return <ShadcnCommandShortcut ref={ref} {...props} />;
144
+ }
145
+ )
146
+ );
147
+ CommandShortcut.displayName = "CommandShortcut";
@@ -0,0 +1,20 @@
1
+ export {
2
+ Command,
3
+ CommandDialog,
4
+ CommandEmpty,
5
+ CommandGroup,
6
+ CommandInput,
7
+ CommandItem,
8
+ CommandList,
9
+ CommandSeparator,
10
+ CommandShortcut,
11
+ type CommandProps,
12
+ type CommandDialogProps,
13
+ type CommandEmptyProps,
14
+ type CommandGroupProps,
15
+ type CommandInputProps,
16
+ type CommandItemProps,
17
+ type CommandListProps,
18
+ type CommandSeparatorProps,
19
+ type CommandShortcutProps,
20
+ } from "./Command";
@@ -0,0 +1,390 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import * as React from "react"
3
+ import {
4
+ Dialog,
5
+ DialogClose,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogFooter,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DialogTrigger,
12
+ } from "./Dialog"
13
+ import { Button } from "../Button"
14
+ import { Input } from "../Input"
15
+
16
+ /**
17
+ * Dialog Primitive Stories
18
+ *
19
+ * The Dialog component provides an accessible modal overlay for focused user interactions.
20
+ * It's built on Radix UI Dialog primitive with comprehensive keyboard and screen reader support.
21
+ *
22
+ * ## Accessibility Features
23
+ * - Focus is trapped within the dialog when open
24
+ * - Focus returns to trigger element on close
25
+ * - Escape key closes the dialog
26
+ * - Screen reader announces dialog content
27
+ * - Proper ARIA attributes (role="dialog", aria-labelledby, aria-describedby)
28
+ *
29
+ * ## Usage Guidelines
30
+ * - Always include DialogTitle for accessibility (screen readers)
31
+ * - Use DialogDescription for additional context
32
+ * - Keep dialog content focused and concise
33
+ * - Provide clear action buttons in DialogFooter
34
+ * - Use for critical actions, confirmations, or complex forms
35
+ *
36
+ * ## When to Use
37
+ * - Collecting user input in a focused context
38
+ * - Displaying important information that requires user acknowledgment
39
+ * - Confirming destructive or important actions
40
+ * - Multi-step workflows that need isolation
41
+ *
42
+ * ## When NOT to Use
43
+ * - For simple notifications (use Toast or Alert instead)
44
+ * - For irreversible destructive actions (use AlertDialog instead)
45
+ * - For non-blocking information (use Popover or Tooltip instead)
46
+ */
47
+ const meta = {
48
+ title: "Primitives/Dialog",
49
+ component: Dialog,
50
+ parameters: {
51
+ layout: "centered",
52
+ docs: {
53
+ description: {
54
+ component:
55
+ "A modal dialog component with accessible focus management and keyboard navigation. Built on Radix UI Dialog primitive.",
56
+ },
57
+ },
58
+ },
59
+ tags: ["autodocs"],
60
+ } satisfies Meta<typeof Dialog>
61
+
62
+ export default meta
63
+ type Story = StoryObj<typeof meta>
64
+
65
+ /**
66
+ * Default Dialog
67
+ *
68
+ * Basic dialog with title, description, and action buttons.
69
+ * This is the most common dialog pattern.
70
+ */
71
+ export const Default: Story = {
72
+ render: () => (
73
+ <Dialog>
74
+ <DialogTrigger asChild>
75
+ <Button variant="outline">Open Dialog</Button>
76
+ </DialogTrigger>
77
+ <DialogContent>
78
+ <DialogHeader>
79
+ <DialogTitle>Dialog Title</DialogTitle>
80
+ <DialogDescription>
81
+ This is a description that provides additional context about the
82
+ dialog's purpose.
83
+ </DialogDescription>
84
+ </DialogHeader>
85
+ <div className="py-4">
86
+ <p className="text-sm">
87
+ Dialog body content goes here. You can include any components or
88
+ information needed for this interaction.
89
+ </p>
90
+ </div>
91
+ <DialogFooter>
92
+ <DialogClose asChild>
93
+ <Button variant="outline">Cancel</Button>
94
+ </DialogClose>
95
+ <Button>Confirm</Button>
96
+ </DialogFooter>
97
+ </DialogContent>
98
+ </Dialog>
99
+ ),
100
+ }
101
+
102
+ /**
103
+ * Form Dialog
104
+ *
105
+ * Dialog containing a form with input fields.
106
+ * Useful for collecting structured user input.
107
+ */
108
+ export const FormDialog: Story = {
109
+ render: () => (
110
+ <Dialog>
111
+ <DialogTrigger asChild>
112
+ <Button>Create Account</Button>
113
+ </DialogTrigger>
114
+ <DialogContent>
115
+ <DialogHeader>
116
+ <DialogTitle>Create Account</DialogTitle>
117
+ <DialogDescription>
118
+ Enter your details to create a new account.
119
+ </DialogDescription>
120
+ </DialogHeader>
121
+ <div className="grid gap-4 py-4">
122
+ <div className="grid gap-2">
123
+ <label htmlFor="name" className="text-sm font-medium">
124
+ Name
125
+ </label>
126
+ <Input id="name" placeholder="Enter your name" />
127
+ </div>
128
+ <div className="grid gap-2">
129
+ <label htmlFor="email" className="text-sm font-medium">
130
+ Email
131
+ </label>
132
+ <Input id="email" type="email" placeholder="Enter your email" />
133
+ </div>
134
+ <div className="grid gap-2">
135
+ <label htmlFor="password" className="text-sm font-medium">
136
+ Password
137
+ </label>
138
+ <Input
139
+ id="password"
140
+ type="password"
141
+ placeholder="Enter your password"
142
+ />
143
+ </div>
144
+ </div>
145
+ <DialogFooter>
146
+ <DialogClose asChild>
147
+ <Button variant="outline">Cancel</Button>
148
+ </DialogClose>
149
+ <Button type="submit">Create Account</Button>
150
+ </DialogFooter>
151
+ </DialogContent>
152
+ </Dialog>
153
+ ),
154
+ }
155
+
156
+ /**
157
+ * Confirmation Dialog
158
+ *
159
+ * Dialog for confirming user actions.
160
+ * Use clear action verbs in button labels.
161
+ */
162
+ export const ConfirmationDialog: Story = {
163
+ render: () => (
164
+ <Dialog>
165
+ <DialogTrigger asChild>
166
+ <Button variant="outline">Save Changes</Button>
167
+ </DialogTrigger>
168
+ <DialogContent>
169
+ <DialogHeader>
170
+ <DialogTitle>Are you sure?</DialogTitle>
171
+ <DialogDescription>
172
+ This will save all your changes and update the document.
173
+ </DialogDescription>
174
+ </DialogHeader>
175
+ <div className="py-4">
176
+ <p className="text-sm text-muted-foreground">
177
+ Your changes will be saved permanently and cannot be undone.
178
+ </p>
179
+ </div>
180
+ <DialogFooter>
181
+ <DialogClose asChild>
182
+ <Button variant="outline">Cancel</Button>
183
+ </DialogClose>
184
+ <Button>Save Changes</Button>
185
+ </DialogFooter>
186
+ </DialogContent>
187
+ </Dialog>
188
+ ),
189
+ }
190
+
191
+ /**
192
+ * No Close Button Dialog
193
+ *
194
+ * Dialog without the close button in the top-right corner.
195
+ * Forces user to use explicit action buttons.
196
+ */
197
+ export const NoCloseButton: Story = {
198
+ render: () => (
199
+ <Dialog>
200
+ <DialogTrigger asChild>
201
+ <Button variant="outline">Open Dialog</Button>
202
+ </DialogTrigger>
203
+ <DialogContent showCloseButton={false}>
204
+ <DialogHeader>
205
+ <DialogTitle>Action Required</DialogTitle>
206
+ <DialogDescription>
207
+ Please make a selection to continue.
208
+ </DialogDescription>
209
+ </DialogHeader>
210
+ <div className="py-4">
211
+ <p className="text-sm">
212
+ This dialog requires you to make an explicit choice using the
213
+ buttons below.
214
+ </p>
215
+ </div>
216
+ <DialogFooter>
217
+ <DialogClose asChild>
218
+ <Button variant="outline">Decline</Button>
219
+ </DialogClose>
220
+ <DialogClose asChild>
221
+ <Button>Accept</Button>
222
+ </DialogClose>
223
+ </DialogFooter>
224
+ </DialogContent>
225
+ </Dialog>
226
+ ),
227
+ }
228
+
229
+ /**
230
+ * Scrollable Content Dialog
231
+ *
232
+ * Dialog with long content that requires scrolling.
233
+ * Content area automatically scrolls while header and footer remain fixed.
234
+ */
235
+ export const ScrollableContent: Story = {
236
+ render: () => (
237
+ <Dialog>
238
+ <DialogTrigger asChild>
239
+ <Button variant="outline">View Terms</Button>
240
+ </DialogTrigger>
241
+ <DialogContent className="max-h-[80vh]">
242
+ <DialogHeader>
243
+ <DialogTitle>Terms and Conditions</DialogTitle>
244
+ <DialogDescription>
245
+ Please read our terms and conditions carefully.
246
+ </DialogDescription>
247
+ </DialogHeader>
248
+ <div className="overflow-y-auto py-4 max-h-[50vh]">
249
+ {Array.from({ length: 20 }).map((_, i) => (
250
+ <p key={i} className="text-sm mb-4">
251
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
252
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
253
+ enim ad minim veniam, quis nostrud exercitation ullamco laboris.
254
+ </p>
255
+ ))}
256
+ </div>
257
+ <DialogFooter>
258
+ <DialogClose asChild>
259
+ <Button variant="outline">Decline</Button>
260
+ </DialogClose>
261
+ <Button>Accept</Button>
262
+ </DialogFooter>
263
+ </DialogContent>
264
+ </Dialog>
265
+ ),
266
+ }
267
+
268
+ /**
269
+ * Custom Width Dialog
270
+ *
271
+ * Dialog with custom width using className override.
272
+ * Default max-width is 'sm:max-w-lg'.
273
+ */
274
+ export const CustomWidth: Story = {
275
+ render: () => (
276
+ <Dialog>
277
+ <DialogTrigger asChild>
278
+ <Button variant="outline">Open Wide Dialog</Button>
279
+ </DialogTrigger>
280
+ <DialogContent className="sm:max-w-3xl">
281
+ <DialogHeader>
282
+ <DialogTitle>Wide Dialog</DialogTitle>
283
+ <DialogDescription>
284
+ This dialog has a custom width to accommodate wider content.
285
+ </DialogDescription>
286
+ </DialogHeader>
287
+ <div className="py-4">
288
+ <p className="text-sm">
289
+ You can customize the dialog width by passing a className with
290
+ max-width utilities. This example uses 'sm:max-w-3xl'.
291
+ </p>
292
+ </div>
293
+ <DialogFooter>
294
+ <DialogClose asChild>
295
+ <Button variant="outline">Close</Button>
296
+ </DialogClose>
297
+ </DialogFooter>
298
+ </DialogContent>
299
+ </Dialog>
300
+ ),
301
+ }
302
+
303
+ /**
304
+ * Controlled Dialog
305
+ *
306
+ * Dialog with controlled open state using React state.
307
+ * Useful when you need to programmatically control the dialog.
308
+ */
309
+ export const ControlledDialog: Story = {
310
+ render: () => {
311
+ const [open, setOpen] = React.useState(false)
312
+
313
+ return (
314
+ <>
315
+ <div className="flex gap-2">
316
+ <Button onClick={() => setOpen(true)}>Open Dialog</Button>
317
+ <Button
318
+ variant="outline"
319
+ onClick={() => setOpen(false)}
320
+ disabled={!open}
321
+ >
322
+ Close Externally
323
+ </Button>
324
+ </div>
325
+ <Dialog open={open} onOpenChange={setOpen}>
326
+ <DialogContent>
327
+ <DialogHeader>
328
+ <DialogTitle>Controlled Dialog</DialogTitle>
329
+ <DialogDescription>
330
+ This dialog's open state is controlled by React state.
331
+ </DialogDescription>
332
+ </DialogHeader>
333
+ <div className="py-4">
334
+ <p className="text-sm">
335
+ You can control this dialog programmatically using the external
336
+ buttons.
337
+ </p>
338
+ </div>
339
+ <DialogFooter>
340
+ <Button variant="outline" onClick={() => setOpen(false)}>
341
+ Close
342
+ </Button>
343
+ </DialogFooter>
344
+ </DialogContent>
345
+ </Dialog>
346
+ </>
347
+ )
348
+ },
349
+ }
350
+
351
+ /**
352
+ * Dark Mode Dialog
353
+ *
354
+ * Dialog appearance in dark mode.
355
+ * All dialog styles are theme-aware and adapt to dark mode automatically.
356
+ */
357
+ export const DarkMode: Story = {
358
+ parameters: {
359
+ backgrounds: { default: "dark" },
360
+ },
361
+ render: () => (
362
+ <div className="dark">
363
+ <Dialog>
364
+ <DialogTrigger asChild>
365
+ <Button variant="outline">Open Dialog</Button>
366
+ </DialogTrigger>
367
+ <DialogContent>
368
+ <DialogHeader>
369
+ <DialogTitle>Dark Mode Dialog</DialogTitle>
370
+ <DialogDescription>
371
+ This dialog automatically adapts to dark mode.
372
+ </DialogDescription>
373
+ </DialogHeader>
374
+ <div className="py-4">
375
+ <p className="text-sm">
376
+ All colors and contrast ratios are optimized for dark mode,
377
+ ensuring WCAG 2.1 Level AA compliance.
378
+ </p>
379
+ </div>
380
+ <DialogFooter>
381
+ <DialogClose asChild>
382
+ <Button variant="outline">Cancel</Button>
383
+ </DialogClose>
384
+ <Button>Confirm</Button>
385
+ </DialogFooter>
386
+ </DialogContent>
387
+ </Dialog>
388
+ </div>
389
+ ),
390
+ }