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,142 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { PageLayout } from './PageLayout'
|
|
3
|
+
import { usePageLayoutMock } from './usePageLayout.mock'
|
|
4
|
+
import { mockSidebarConfig, mockHeaderConfig } from './PageLayout.mocks'
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Features/PageLayout',
|
|
8
|
+
component: PageLayout,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'fullscreen',
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta<typeof PageLayout>
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
type Story = StoryObj<typeof meta>
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Default PageLayout
|
|
20
|
+
*
|
|
21
|
+
* Complete page layout with sidebar, header, and content area.
|
|
22
|
+
*/
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
sidebar: mockSidebarConfig,
|
|
26
|
+
header: mockHeaderConfig,
|
|
27
|
+
defaultSidebarOpen: true,
|
|
28
|
+
children: (
|
|
29
|
+
<div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
|
|
30
|
+
<div className="px-4 lg:px-6">
|
|
31
|
+
<h2 className="text-2xl font-bold">Welcome to Dashboard</h2>
|
|
32
|
+
<p className="text-muted-foreground">
|
|
33
|
+
This is the main content area. The sidebar can be toggled using the button in the header.
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
<div className="grid gap-4 px-4 md:grid-cols-2 lg:grid-cols-3 lg:px-6">
|
|
37
|
+
{[1, 2, 3].map((i) => (
|
|
38
|
+
<div key={i} className="rounded-lg border p-4">
|
|
39
|
+
<h3 className="font-semibold">Card {i}</h3>
|
|
40
|
+
<p className="text-sm text-muted-foreground">Sample content</p>
|
|
41
|
+
</div>
|
|
42
|
+
))}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
),
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* With State Management
|
|
51
|
+
*
|
|
52
|
+
* PageLayout with mock hook for state management demonstration.
|
|
53
|
+
*/
|
|
54
|
+
export const WithStateManagement: Story = {
|
|
55
|
+
render: () => {
|
|
56
|
+
const layoutState = usePageLayoutMock()
|
|
57
|
+
return (
|
|
58
|
+
<PageLayout
|
|
59
|
+
sidebar={mockSidebarConfig}
|
|
60
|
+
header={mockHeaderConfig}
|
|
61
|
+
defaultSidebarOpen={layoutState.isSidebarOpen}
|
|
62
|
+
>
|
|
63
|
+
<div className="@container/main flex flex-1 flex-col gap-2">
|
|
64
|
+
<div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
|
|
65
|
+
<div className="px-4 lg:px-6">
|
|
66
|
+
<h2 className="text-2xl font-bold">State Management Demo</h2>
|
|
67
|
+
<p className="text-muted-foreground">
|
|
68
|
+
Sidebar is {layoutState.isSidebarOpen ? 'open' : 'closed'}
|
|
69
|
+
</p>
|
|
70
|
+
</div>
|
|
71
|
+
<div className="px-4 lg:px-6">
|
|
72
|
+
<div className="rounded-lg border p-4">
|
|
73
|
+
<h3 className="font-semibold">Layout Config</h3>
|
|
74
|
+
<pre className="mt-2 text-sm">
|
|
75
|
+
{JSON.stringify(layoutState.layoutConfig, null, 2)}
|
|
76
|
+
</pre>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</PageLayout>
|
|
82
|
+
)
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Collapsed Sidebar
|
|
88
|
+
*
|
|
89
|
+
* PageLayout with sidebar collapsed by default.
|
|
90
|
+
*/
|
|
91
|
+
export const CollapsedSidebar: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
sidebar: mockSidebarConfig,
|
|
94
|
+
header: mockHeaderConfig,
|
|
95
|
+
defaultSidebarOpen: false,
|
|
96
|
+
children: (
|
|
97
|
+
<div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
|
|
98
|
+
<div className="px-4 lg:px-6">
|
|
99
|
+
<h2 className="text-2xl font-bold">Collapsed Sidebar</h2>
|
|
100
|
+
<p className="text-muted-foreground">
|
|
101
|
+
The sidebar starts collapsed. Click the trigger button to expand it.
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* With Multiple Sections
|
|
111
|
+
*
|
|
112
|
+
* PageLayout with sidebar containing multiple navigation sections.
|
|
113
|
+
*/
|
|
114
|
+
export const WithMultipleSections: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
sidebar: {
|
|
117
|
+
...mockSidebarConfig,
|
|
118
|
+
secondaryNavigation: [
|
|
119
|
+
{ title: 'Settings', url: '#', icon: 'settings' },
|
|
120
|
+
{ title: 'Help', url: '#', icon: 'help-circle' },
|
|
121
|
+
],
|
|
122
|
+
documents: [
|
|
123
|
+
{ title: 'Project A', url: '#', icon: 'file' },
|
|
124
|
+
{ title: 'Project B', url: '#', icon: 'file' },
|
|
125
|
+
{ title: 'Project C', url: '#', icon: 'file' },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
header: mockHeaderConfig,
|
|
129
|
+
defaultSidebarOpen: true,
|
|
130
|
+
children: (
|
|
131
|
+
<div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
|
|
132
|
+
<div className="px-4 lg:px-6">
|
|
133
|
+
<h2 className="text-2xl font-bold">Multiple Sections</h2>
|
|
134
|
+
<p className="text-muted-foreground">
|
|
135
|
+
The sidebar contains main navigation, documents, and secondary navigation sections.
|
|
136
|
+
</p>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
),
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { AppSidebar, type AppSidebarProps } from "@/components/blocks/AppSidebar"
|
|
3
|
+
import { LayoutProvider } from "@/components/blocks/LayoutProvider"
|
|
4
|
+
import { AppHeader, type AppHeaderProps } from "@/components/composites/AppHeader"
|
|
5
|
+
import { PageContainer } from "@/components/composites/PageContainer"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* PageLayout Feature
|
|
9
|
+
*
|
|
10
|
+
* Complete page layout with sidebar, header, and content area.
|
|
11
|
+
* Composes AppSidebar block and AppHeader composite with SidebarProvider.
|
|
12
|
+
*
|
|
13
|
+
* This is a self-contained feature component that handles all its own providers
|
|
14
|
+
* and layout internally. No external wrapping is required.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <PageLayout
|
|
19
|
+
* sidebar={sidebarConfig}
|
|
20
|
+
* header={headerConfig}
|
|
21
|
+
* defaultSidebarOpen={true}
|
|
22
|
+
* >
|
|
23
|
+
* {children}
|
|
24
|
+
* </PageLayout>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface PageLayoutProps {
|
|
29
|
+
/**
|
|
30
|
+
* Sidebar configuration
|
|
31
|
+
*/
|
|
32
|
+
sidebar: AppSidebarProps
|
|
33
|
+
/**
|
|
34
|
+
* Header configuration
|
|
35
|
+
*/
|
|
36
|
+
header: AppHeaderProps
|
|
37
|
+
/**
|
|
38
|
+
* Page content
|
|
39
|
+
*/
|
|
40
|
+
children: React.ReactNode
|
|
41
|
+
/**
|
|
42
|
+
* Additional CSS classes
|
|
43
|
+
*/
|
|
44
|
+
className?: string
|
|
45
|
+
/**
|
|
46
|
+
* Whether the sidebar is open by default
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
defaultSidebarOpen?: boolean
|
|
50
|
+
/**
|
|
51
|
+
* Sidebar width CSS variable value
|
|
52
|
+
* @default "var(--spacing-sidebar-width)"
|
|
53
|
+
*/
|
|
54
|
+
sidebarWidth?: string
|
|
55
|
+
/**
|
|
56
|
+
* Sidebar icon width CSS variable value
|
|
57
|
+
* @default "var(--spacing-sidebar-width-icon)"
|
|
58
|
+
*/
|
|
59
|
+
sidebarWidthIcon?: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* PageLayout component
|
|
64
|
+
*
|
|
65
|
+
* Provides a complete page layout with sidebar, header, and content area.
|
|
66
|
+
* Includes SidebarProvider for state management.
|
|
67
|
+
*/
|
|
68
|
+
export const PageLayout = React.memo<PageLayoutProps>(
|
|
69
|
+
({
|
|
70
|
+
sidebar,
|
|
71
|
+
header,
|
|
72
|
+
children,
|
|
73
|
+
className,
|
|
74
|
+
defaultSidebarOpen = true,
|
|
75
|
+
sidebarWidth = "var(--spacing-sidebar-width)",
|
|
76
|
+
sidebarWidthIcon = "var(--spacing-sidebar-width-icon)",
|
|
77
|
+
}) => {
|
|
78
|
+
return (
|
|
79
|
+
<LayoutProvider
|
|
80
|
+
defaultOpen={defaultSidebarOpen}
|
|
81
|
+
sidebarWidth={sidebarWidth}
|
|
82
|
+
sidebarWidthIcon={sidebarWidthIcon}
|
|
83
|
+
>
|
|
84
|
+
<AppSidebar {...sidebar} />
|
|
85
|
+
<PageContainer className={className}>
|
|
86
|
+
<AppHeader {...header} />
|
|
87
|
+
<div className="flex flex-1 flex-col">{children}</div>
|
|
88
|
+
</PageContainer>
|
|
89
|
+
</LayoutProvider>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
PageLayout.displayName = "PageLayout"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook contract for PageLayout feature
|
|
3
|
+
* Manages sidebar state and layout configuration
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const { isSidebarOpen, toggleSidebar, layoutConfig } = usePageLayout()
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export interface UsePageLayoutReturn {
|
|
11
|
+
/** Whether the sidebar is currently open */
|
|
12
|
+
isSidebarOpen: boolean
|
|
13
|
+
/** Toggle sidebar open/closed */
|
|
14
|
+
toggleSidebar: () => void
|
|
15
|
+
/** Set sidebar open state */
|
|
16
|
+
setSidebarOpen: (open: boolean) => void
|
|
17
|
+
/** Current layout configuration */
|
|
18
|
+
layoutConfig: {
|
|
19
|
+
sidebarWidth: string
|
|
20
|
+
headerHeight: string
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type UsePageLayout = () => UsePageLayoutReturn
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import type { UsePageLayoutReturn } from './usePageLayout.d'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Mock implementation of usePageLayout hook for Storybook stories
|
|
6
|
+
*/
|
|
7
|
+
export const usePageLayoutMock = (): UsePageLayoutReturn => {
|
|
8
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(true)
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
isSidebarOpen,
|
|
12
|
+
toggleSidebar: () => setIsSidebarOpen((prev) => !prev),
|
|
13
|
+
setSidebarOpen: setIsSidebarOpen,
|
|
14
|
+
layoutConfig: {
|
|
15
|
+
sidebarWidth: 'var(--spacing-sidebar-width-mobile)',
|
|
16
|
+
headerHeight: 'var(--spacing-header-height)',
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# RefinementPanel Feature
|
|
2
|
+
|
|
3
|
+
A comprehensive UI component for managing AI-powered refinement workflows with multi-agent conversations, file changes, and approval processes.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
This feature follows the **extensible component pattern** with clear separation between:
|
|
8
|
+
- **Component Layer**: Pure UI component (`RefinementPanel.tsx`)
|
|
9
|
+
- **Hook Contract**: Interface definition (`useRefinementPanel.d.ts`)
|
|
10
|
+
- **Mock Implementation**: Storybook testing (`useRefinementPanel.mock.ts`)
|
|
11
|
+
- **Application Layer**: Real implementation (in your app)
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### In Your Application
|
|
16
|
+
|
|
17
|
+
Implement the hook contract with real API calls:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// app/hooks/useRefinementPanel.ts
|
|
21
|
+
import { useState } from 'react';
|
|
22
|
+
import type { UseRefinementPanelReturn } from 'ui-lib/components/features/RefinementPanel';
|
|
23
|
+
|
|
24
|
+
export function useRefinementPanel(): UseRefinementPanelReturn {
|
|
25
|
+
const [messages, setMessages] = useState([]);
|
|
26
|
+
const [fileChanges, setFileChanges] = useState([]);
|
|
27
|
+
const [loading, setLoading] = useState(false);
|
|
28
|
+
|
|
29
|
+
const handleSubmit = async () => {
|
|
30
|
+
setLoading(true);
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch('/api/refinement/submit', {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
body: JSON.stringify({ messages }),
|
|
35
|
+
});
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
setMessages(data.messages);
|
|
38
|
+
setFileChanges(data.fileChanges);
|
|
39
|
+
} finally {
|
|
40
|
+
setLoading(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const handleApprove = async () => {
|
|
45
|
+
setLoading(true);
|
|
46
|
+
try {
|
|
47
|
+
await fetch('/api/refinement/approve', {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
body: JSON.stringify({ fileChanges }),
|
|
50
|
+
});
|
|
51
|
+
setFileChanges([]);
|
|
52
|
+
} finally {
|
|
53
|
+
setLoading(false);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleReject = async () => {
|
|
58
|
+
setLoading(true);
|
|
59
|
+
try {
|
|
60
|
+
await fetch('/api/refinement/reject', {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
});
|
|
63
|
+
setFileChanges([]);
|
|
64
|
+
} finally {
|
|
65
|
+
setLoading(false);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
messages,
|
|
71
|
+
fileChanges,
|
|
72
|
+
loading,
|
|
73
|
+
handleSubmit,
|
|
74
|
+
handleApprove,
|
|
75
|
+
handleReject,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Then use it with the component:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
// app/components/RefinementContainer.tsx
|
|
84
|
+
import { RefinementPanel } from 'ui-lib/components/features/RefinementPanel';
|
|
85
|
+
import { useRefinementPanel } from '../hooks/useRefinementPanel';
|
|
86
|
+
|
|
87
|
+
export function RefinementContainer() {
|
|
88
|
+
const { messages, fileChanges, loading, handleSubmit, handleApprove, handleReject } =
|
|
89
|
+
useRefinementPanel();
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<RefinementPanel
|
|
93
|
+
messages={messages}
|
|
94
|
+
fileChanges={fileChanges}
|
|
95
|
+
loading={loading}
|
|
96
|
+
onSubmit={handleSubmit}
|
|
97
|
+
onApprove={handleApprove}
|
|
98
|
+
onReject={handleReject}
|
|
99
|
+
placeholder="Ask a question or describe a task..."
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### In Storybook
|
|
106
|
+
|
|
107
|
+
Use the mock hook for visual testing:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { RefinementPanel, useMockRefinementPanel } from 'ui-lib/components/features/RefinementPanel';
|
|
111
|
+
|
|
112
|
+
export const Interactive = () => {
|
|
113
|
+
const { messages, fileChanges, handleSubmit, handleApprove, handleReject } =
|
|
114
|
+
useMockRefinementPanel({
|
|
115
|
+
initialMessages: [...],
|
|
116
|
+
reviewMessages: [...],
|
|
117
|
+
reviewFileChanges: [...],
|
|
118
|
+
apiDelay: 800,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<RefinementPanel
|
|
123
|
+
messages={messages}
|
|
124
|
+
fileChanges={fileChanges}
|
|
125
|
+
onSubmit={handleSubmit}
|
|
126
|
+
onApprove={handleApprove}
|
|
127
|
+
onReject={handleReject}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Hook Contract
|
|
134
|
+
|
|
135
|
+
### `UseRefinementPanelReturn`
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface UseRefinementPanelReturn {
|
|
139
|
+
messages: RefinementMessage[];
|
|
140
|
+
fileChanges: FileChangeData[];
|
|
141
|
+
loading: boolean;
|
|
142
|
+
handleSubmit: () => Promise<void> | void;
|
|
143
|
+
handleApprove: () => Promise<void> | void;
|
|
144
|
+
handleReject: () => Promise<void> | void;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Component Props
|
|
149
|
+
|
|
150
|
+
### `RefinementPanelProps`
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
interface RefinementPanelProps {
|
|
154
|
+
messages?: RefinementMessage[];
|
|
155
|
+
fileChanges?: FileChangeData[];
|
|
156
|
+
loading?: boolean;
|
|
157
|
+
placeholder?: string;
|
|
158
|
+
onSubmit?: (message: PromptInputMessage) => void;
|
|
159
|
+
onApprove?: () => void;
|
|
160
|
+
onReject?: () => void;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## States
|
|
165
|
+
|
|
166
|
+
The component supports multiple workflow states:
|
|
167
|
+
|
|
168
|
+
1. **Input State**: Clean interface for submitting refinement requests
|
|
169
|
+
2. **Review State**: Multi-agent processing with file changes and approval workflow
|
|
170
|
+
3. **Loading State**: Visual feedback during async operations
|
|
171
|
+
|
|
172
|
+
## Design Principles
|
|
173
|
+
|
|
174
|
+
- **Declarative**: Component describes what happens visually, not how logic works
|
|
175
|
+
- **Extensible**: Event props allow integration with any backend
|
|
176
|
+
- **Stateless**: Business logic lives outside the component
|
|
177
|
+
- **Testable**: Mock hook enables isolated visual testing
|
|
178
|
+
|
|
179
|
+
## Files
|
|
180
|
+
|
|
181
|
+
- `RefinementPanel.tsx` - Main component implementation
|
|
182
|
+
- `RefinementPanel.stories.tsx` - Storybook stories and examples
|
|
183
|
+
- `useRefinementPanel.d.ts` - Hook contract definition
|
|
184
|
+
- `useRefinementPanel.mock.ts` - Mock implementation for testing
|
|
185
|
+
- `index.ts` - Public exports
|
|
186
|
+
|
|
187
|
+
## References
|
|
188
|
+
|
|
189
|
+
See `.claude/skills/design-system/references/extendable-with-state-stories.md` for the complete pattern documentation.
|