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.
- package/README.md +307 -0
- package/components/ai-elements/actions.tsx +65 -0
- package/components/ai-elements/artifact.tsx +147 -0
- package/components/ai-elements/branch.tsx +212 -0
- package/components/ai-elements/canvas.tsx +24 -0
- package/components/ai-elements/chain-of-thought.tsx +228 -0
- package/components/ai-elements/code-block.tsx +179 -0
- package/components/ai-elements/confirmation.tsx +169 -0
- package/components/ai-elements/connection.tsx +28 -0
- package/components/ai-elements/context.tsx +408 -0
- package/components/ai-elements/controls.tsx +18 -0
- package/components/ai-elements/conversation.tsx +97 -0
- package/components/ai-elements/edge.tsx +140 -0
- package/components/ai-elements/image.tsx +24 -0
- package/components/ai-elements/inline-citation.tsx +287 -0
- package/components/ai-elements/loader.tsx +96 -0
- package/components/ai-elements/message.tsx +80 -0
- package/components/ai-elements/node.tsx +71 -0
- package/components/ai-elements/open-in-chat.tsx +363 -0
- package/components/ai-elements/panel.tsx +15 -0
- package/components/ai-elements/plan.tsx +142 -0
- package/components/ai-elements/prompt-input.tsx +1352 -0
- package/components/ai-elements/queue.tsx +274 -0
- package/components/ai-elements/reasoning.tsx +178 -0
- package/components/ai-elements/response.tsx +22 -0
- package/components/ai-elements/shimmer.tsx +64 -0
- package/components/ai-elements/sources.tsx +77 -0
- package/components/ai-elements/suggestion.tsx +56 -0
- package/components/ai-elements/task.tsx +87 -0
- package/components/ai-elements/tool.tsx +179 -0
- package/components/ai-elements/toolbar.tsx +16 -0
- package/components/ai-elements/web-preview.tsx +263 -0
- package/components/blocks/AIConversation/AIConversation.stories.tsx +164 -0
- package/components/blocks/AIConversation/AIConversation.tsx +186 -0
- package/components/blocks/AIConversation/index.ts +8 -0
- package/components/blocks/AppSidebar/AppSidebar.stories.tsx +63 -0
- package/components/blocks/AppSidebar/AppSidebar.tsx +87 -0
- package/components/blocks/AppSidebar/index.ts +2 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.stories.tsx +341 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.tsx +255 -0
- package/components/blocks/DocumentEditorWithComments/index.ts +9 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.stories.tsx +207 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.tsx +143 -0
- package/components/blocks/FileChangeQueue/index.ts +7 -0
- package/components/blocks/LayoutProvider/LayoutProvider.tsx +34 -0
- package/components/blocks/LayoutProvider/index.ts +1 -0
- package/components/blocks/index.ts +2 -0
- package/components/composites/AgentIndicator/AgentIndicator.stories.tsx +154 -0
- package/components/composites/AgentIndicator/AgentIndicator.tsx +102 -0
- package/components/composites/AgentIndicator/index.ts +8 -0
- package/components/composites/AppHeader/AppHeader.stories.tsx +46 -0
- package/components/composites/AppHeader/AppHeader.tsx +24 -0
- package/components/composites/AppHeader/index.ts +2 -0
- package/components/composites/CommentBox/CommentBox.stories.tsx +192 -0
- package/components/composites/CommentBox/CommentBox.tsx +364 -0
- package/components/composites/CommentBox/index.ts +8 -0
- package/components/composites/Confirmation/Confirmation.stories.tsx +151 -0
- package/components/composites/Confirmation/Confirmation.tsx +93 -0
- package/components/composites/Confirmation/index.ts +7 -0
- package/components/composites/DataTable/DataTable.stories.tsx +35 -0
- package/components/composites/DataTable/DataTable.tsx +95 -0
- package/components/composites/DataTable/index.ts +2 -0
- package/components/composites/DocumentEditor/DocumentEditor.css +106 -0
- package/components/composites/DocumentEditor/DocumentEditor.stories.tsx +927 -0
- package/components/composites/DocumentEditor/DocumentEditor.tsx +279 -0
- package/components/composites/DocumentEditor/index.ts +8 -0
- package/components/composites/FileQueue/FileQueue.stories.tsx +175 -0
- package/components/composites/FileQueue/FileQueue.tsx +161 -0
- package/components/composites/FileQueue/FileStatusBadge.tsx +74 -0
- package/components/composites/FileQueue/index.ts +24 -0
- package/components/composites/InteractiveChart/InteractiveChart.stories.tsx +49 -0
- package/components/composites/InteractiveChart/InteractiveChart.tsx +69 -0
- package/components/composites/InteractiveChart/index.ts +2 -0
- package/components/composites/ModeToggle/ModeToggle.stories.tsx +212 -0
- package/components/composites/ModeToggle/ModeToggle.tsx +100 -0
- package/components/composites/ModeToggle/index.ts +7 -0
- package/components/composites/NavUser/NavUser.stories.tsx +50 -0
- package/components/composites/NavUser/NavUser.tsx +60 -0
- package/components/composites/NavUser/index.ts +2 -0
- package/components/composites/NavigationList/NavigationList.stories.tsx +46 -0
- package/components/composites/NavigationList/NavigationList.tsx +46 -0
- package/components/composites/NavigationList/index.ts +2 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.stories.tsx +188 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +72 -0
- package/components/composites/OrchestratorMessage/index.ts +8 -0
- package/components/composites/PageContainer/PageContainer.stories.tsx +41 -0
- package/components/composites/PageContainer/PageContainer.tsx +24 -0
- package/components/composites/PageContainer/index.ts +2 -0
- package/components/composites/PromptInput/PromptInput.stories.tsx +200 -0
- package/components/composites/PromptInput/PromptInput.tsx +129 -0
- package/components/composites/PromptInput/index.ts +8 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.stories.tsx +286 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.tsx +107 -0
- package/components/composites/SpecialistMessage/index.ts +8 -0
- package/components/composites/StatsCard/StatsCard.stories.tsx +76 -0
- package/components/composites/StatsCard/StatsCard.tsx +81 -0
- package/components/composites/StatsCard/index.ts +2 -0
- package/components/composites/TablePagination/TablePagination.stories.tsx +38 -0
- package/components/composites/TablePagination/TablePagination.tsx +119 -0
- package/components/composites/TablePagination/index.ts +2 -0
- package/components/composites/TableToolbar/TableToolbar.stories.tsx +60 -0
- package/components/composites/TableToolbar/TableToolbar.tsx +66 -0
- package/components/composites/TableToolbar/index.ts +2 -0
- package/components/composites/ThemeSelector/ThemeSelector.stories.tsx +48 -0
- package/components/composites/ThemeSelector/ThemeSelector.tsx +79 -0
- package/components/composites/ThemeSelector/index.ts +2 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.stories.tsx +49 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.tsx +108 -0
- package/components/composites/ToolCallDisplay/index.ts +8 -0
- package/components/composites/UserMessage/UserMessage.stories.tsx +59 -0
- package/components/composites/UserMessage/UserMessage.tsx +52 -0
- package/components/composites/UserMessage/index.ts +8 -0
- package/components/composites/index.ts +90 -0
- package/components/features/AIDocEditor/AIDocEditor.behaviors.stories.tsx +451 -0
- package/components/features/AIDocEditor/AIDocEditor.mocks.ts +96 -0
- package/components/features/AIDocEditor/AIDocEditor.stories.tsx +140 -0
- package/components/features/AIDocEditor/AIDocEditor.tsx +130 -0
- package/components/features/AIDocEditor/index.ts +8 -0
- package/components/features/AIDocEditor/useAIDocEditor.d.ts +97 -0
- package/components/features/AIDocEditor/useAIDocEditor.mock.ts +83 -0
- package/components/features/PageLayout/PageLayout.behaviors.stories.tsx +119 -0
- package/components/features/PageLayout/PageLayout.mocks.ts +27 -0
- package/components/features/PageLayout/PageLayout.stories.tsx +142 -0
- package/components/features/PageLayout/PageLayout.tsx +94 -0
- package/components/features/PageLayout/index.ts +4 -0
- package/components/features/PageLayout/usePageLayout.d.ts +24 -0
- package/components/features/PageLayout/usePageLayout.mock.ts +19 -0
- package/components/features/RefinementPanel/README.md +189 -0
- package/components/features/RefinementPanel/RefinementPanel.behaviors.stories.tsx +475 -0
- package/components/features/RefinementPanel/RefinementPanel.mocks.ts +131 -0
- package/components/features/RefinementPanel/RefinementPanel.stories.tsx +141 -0
- package/components/features/RefinementPanel/RefinementPanel.tsx +160 -0
- package/components/features/RefinementPanel/index.ts +25 -0
- package/components/features/RefinementPanel/useRefinementPanel.d.ts +74 -0
- package/components/features/RefinementPanel/useRefinementPanel.mock.ts +121 -0
- package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +379 -0
- package/components/features/SpecNavigator/SpecNavigator.mocks.ts +131 -0
- package/components/features/SpecNavigator/SpecNavigator.stories.tsx +122 -0
- package/components/features/SpecNavigator/SpecNavigator.tsx +43 -0
- package/components/features/SpecNavigator/index.ts +2 -0
- package/components/features/SpecNavigator/useSpecNavigator.d.ts +122 -0
- package/components/features/SpecNavigator/useSpecNavigator.mock.ts +93 -0
- package/components/features/index.ts +18 -0
- package/components/index.ts +14 -0
- package/components/primitives/Accordion/Accordion.stories.tsx +87 -0
- package/components/primitives/Accordion/Accordion.tsx +66 -0
- package/components/primitives/Accordion/index.ts +13 -0
- package/components/primitives/Alert/Alert.stories.tsx +422 -0
- package/components/primitives/Alert/Alert.tsx +61 -0
- package/components/primitives/Alert/index.ts +8 -0
- package/components/primitives/AlertDialog/AlertDialog.stories.tsx +367 -0
- package/components/primitives/AlertDialog/AlertDialog.tsx +182 -0
- package/components/primitives/AlertDialog/index.ts +25 -0
- package/components/primitives/Avatar/Avatar.stories.tsx +321 -0
- package/components/primitives/Avatar/Avatar.tsx +63 -0
- package/components/primitives/Avatar/index.ts +8 -0
- package/components/primitives/Badge/Badge.stories.tsx +74 -0
- package/components/primitives/Badge/Badge.tsx +49 -0
- package/components/primitives/Badge/index.ts +2 -0
- package/components/primitives/Button/Button.stories.tsx +445 -0
- package/components/primitives/Button/Button.tsx +89 -0
- package/components/primitives/Button/index.ts +7 -0
- package/components/primitives/Card/Card.stories.tsx +831 -0
- package/components/primitives/Card/Card.tsx +242 -0
- package/components/primitives/Card/index.ts +30 -0
- package/components/primitives/Carousel/Carousel.stories.tsx +32 -0
- package/components/primitives/Carousel/Carousel.tsx +63 -0
- package/components/primitives/Carousel/index.ts +13 -0
- package/components/primitives/Chart/Chart.stories.tsx +346 -0
- package/components/primitives/Chart/Chart.tsx +117 -0
- package/components/primitives/Chart/index.ts +20 -0
- package/components/primitives/Checkbox/Checkbox.stories.tsx +87 -0
- package/components/primitives/Checkbox/Checkbox.tsx +38 -0
- package/components/primitives/Checkbox/index.ts +2 -0
- package/components/primitives/Collapsible/Collapsible.stories.tsx +38 -0
- package/components/primitives/Collapsible/Collapsible.tsx +39 -0
- package/components/primitives/Collapsible/index.ts +8 -0
- package/components/primitives/Command/Command.stories.tsx +150 -0
- package/components/primitives/Command/Command.tsx +147 -0
- package/components/primitives/Command/index.ts +20 -0
- package/components/primitives/Dialog/Dialog.stories.tsx +390 -0
- package/components/primitives/Dialog/Dialog.tsx +140 -0
- package/components/primitives/Dialog/index.ts +22 -0
- package/components/primitives/Drawer/Drawer.stories.tsx +327 -0
- package/components/primitives/Drawer/Drawer.tsx +208 -0
- package/components/primitives/Drawer/index.ts +27 -0
- package/components/primitives/DropdownMenu/DropdownMenu.stories.tsx +150 -0
- package/components/primitives/DropdownMenu/DropdownMenu.tsx +73 -0
- package/components/primitives/DropdownMenu/index.ts +1 -0
- package/components/primitives/HoverCard/HoverCard.stories.tsx +26 -0
- package/components/primitives/HoverCard/HoverCard.tsx +39 -0
- package/components/primitives/HoverCard/index.ts +8 -0
- package/components/primitives/Icon/Icon.stories.tsx +281 -0
- package/components/primitives/Icon/Icon.tsx +87 -0
- package/components/primitives/Icon/index.ts +8 -0
- package/components/primitives/Input/Input.stories.tsx +370 -0
- package/components/primitives/Input/Input.tsx +88 -0
- package/components/primitives/Input/index.ts +7 -0
- package/components/primitives/InputGroup/InputGroup.stories.tsx +40 -0
- package/components/primitives/InputGroup/InputGroup.tsx +72 -0
- package/components/primitives/InputGroup/index.ts +14 -0
- package/components/primitives/Label/Label.stories.tsx +227 -0
- package/components/primitives/Label/Label.tsx +53 -0
- package/components/primitives/Label/index.ts +7 -0
- package/components/primitives/Popover/Popover.stories.tsx +42 -0
- package/components/primitives/Popover/Popover.tsx +107 -0
- package/components/primitives/Popover/index.ts +2 -0
- package/components/primitives/Progress/Progress.stories.tsx +340 -0
- package/components/primitives/Progress/Progress.tsx +31 -0
- package/components/primitives/Progress/index.ts +1 -0
- package/components/primitives/ScrollArea/ScrollArea.stories.tsx +26 -0
- package/components/primitives/ScrollArea/ScrollArea.tsx +28 -0
- package/components/primitives/ScrollArea/index.ts +6 -0
- package/components/primitives/Select/Select.stories.tsx +288 -0
- package/components/primitives/Select/Select.tsx +162 -0
- package/components/primitives/Select/index.ts +22 -0
- package/components/primitives/Separator/Separator.stories.tsx +264 -0
- package/components/primitives/Separator/Separator.tsx +48 -0
- package/components/primitives/Separator/index.ts +7 -0
- package/components/primitives/Sidebar/Sidebar.stories.tsx +358 -0
- package/components/primitives/Sidebar/Sidebar.tsx +317 -0
- package/components/primitives/Sidebar/index.ts +41 -0
- package/components/primitives/Table/Table.stories.tsx +389 -0
- package/components/primitives/Table/Table.tsx +191 -0
- package/components/primitives/Table/index.ts +26 -0
- package/components/primitives/Tabs/Tabs.stories.tsx +129 -0
- package/components/primitives/Tabs/Tabs.tsx +70 -0
- package/components/primitives/Tabs/index.ts +13 -0
- package/components/primitives/Textarea/Textarea.stories.tsx +358 -0
- package/components/primitives/Textarea/Textarea.tsx +91 -0
- package/components/primitives/Textarea/index.ts +7 -0
- package/components/primitives/ToggleGroup/ToggleGroup.stories.tsx +87 -0
- package/components/primitives/ToggleGroup/ToggleGroup.tsx +52 -0
- package/components/primitives/ToggleGroup/index.ts +6 -0
- package/components/primitives/Tooltip/Tooltip.stories.tsx +336 -0
- package/components/primitives/Tooltip/Tooltip.tsx +78 -0
- package/components/primitives/Tooltip/index.ts +10 -0
- package/components/primitives/index.ts +34 -0
- package/components/ui/accordion.tsx +66 -0
- package/components/ui/alert-dialog.tsx +157 -0
- package/components/ui/alert.tsx +66 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/card.tsx +117 -0
- package/components/ui/carousel.tsx +241 -0
- package/components/ui/chart.tsx +334 -0
- package/components/ui/checkbox.tsx +32 -0
- package/components/ui/collapsible.tsx +33 -0
- package/components/ui/command.tsx +184 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/drawer.tsx +118 -0
- package/components/ui/dropdown-menu.tsx +257 -0
- package/components/ui/hover-card.tsx +44 -0
- package/components/ui/input-group.tsx +170 -0
- package/components/ui/input.tsx +48 -0
- package/components/ui/label.tsx +26 -0
- package/components/ui/popover.tsx +33 -0
- package/components/ui/progress.tsx +31 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/select.tsx +187 -0
- package/components/ui/separator.tsx +31 -0
- package/components/ui/sidebar.tsx +577 -0
- package/components/ui/table.tsx +120 -0
- package/components/ui/tabs.tsx +66 -0
- package/components/ui/textarea.tsx +46 -0
- package/components/ui/toggle-group.tsx +83 -0
- package/components/ui/toggle.tsx +47 -0
- package/components/ui/tooltip.tsx +61 -0
- package/dist/index.cjs +7389 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +75 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +7160 -0
- package/dist/index.js.map +1 -0
- package/hooks/useAIDocReviewer.d.ts +0 -0
- package/lib/utils.ts +6 -0
- package/package.json +140 -0
- package/tokens/color/base.json +14 -0
- package/tokens/color/dark.json +40 -0
- package/tokens/color/green.json +21 -0
- package/tokens/color/light.json +52 -0
- package/tokens/color/neutral.json +20 -0
- package/tokens/color/violet.json +21 -0
- package/tokens/spacing.json +22 -0
- package/utils/ai-editor/format-date.ts +41 -0
- package/utils/ai-editor/index.ts +22 -0
- package/utils/ai-editor/type-guards.ts +72 -0
- package/utils/ai-editor/validation.ts +130 -0
- 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
|
+
}
|