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,129 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./Tabs"
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../Card"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tabs Primitive Stories
|
|
8
|
+
*
|
|
9
|
+
* The Tabs component organizes content into switchable panels with accessible keyboard navigation.
|
|
10
|
+
*
|
|
11
|
+
* ## Accessibility Features
|
|
12
|
+
* - Arrow keys navigate between tabs
|
|
13
|
+
* - Home/End keys jump to first/last tab
|
|
14
|
+
* - Tab key moves focus in/out of tab list
|
|
15
|
+
* - Proper ARIA roles and attributes
|
|
16
|
+
*
|
|
17
|
+
* ## Usage Guidelines
|
|
18
|
+
* - Use for content that naturally divides into categories
|
|
19
|
+
* - Keep tab labels short and descriptive
|
|
20
|
+
* - Ensure content in each tab is independent
|
|
21
|
+
* - Don't nest tabs within tabs
|
|
22
|
+
*/
|
|
23
|
+
const meta = {
|
|
24
|
+
title: "Primitives/Tabs",
|
|
25
|
+
component: Tabs,
|
|
26
|
+
parameters: {
|
|
27
|
+
layout: "padded",
|
|
28
|
+
},
|
|
29
|
+
tags: ["autodocs"],
|
|
30
|
+
} satisfies Meta<typeof Tabs>
|
|
31
|
+
|
|
32
|
+
export default meta
|
|
33
|
+
type Story = StoryObj<typeof meta>
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
render: () => (
|
|
37
|
+
<Tabs defaultValue="account" className="w-[400px]">
|
|
38
|
+
<TabsList>
|
|
39
|
+
<TabsTrigger value="account">Account</TabsTrigger>
|
|
40
|
+
<TabsTrigger value="password">Password</TabsTrigger>
|
|
41
|
+
</TabsList>
|
|
42
|
+
<TabsContent value="account">
|
|
43
|
+
<p className="text-sm">Make changes to your account here.</p>
|
|
44
|
+
</TabsContent>
|
|
45
|
+
<TabsContent value="password">
|
|
46
|
+
<p className="text-sm">Change your password here.</p>
|
|
47
|
+
</TabsContent>
|
|
48
|
+
</Tabs>
|
|
49
|
+
),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const WithCards: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<Tabs defaultValue="overview" className="w-[600px]">
|
|
55
|
+
<TabsList>
|
|
56
|
+
<TabsTrigger value="overview">Overview</TabsTrigger>
|
|
57
|
+
<TabsTrigger value="analytics">Analytics</TabsTrigger>
|
|
58
|
+
<TabsTrigger value="reports">Reports</TabsTrigger>
|
|
59
|
+
<TabsTrigger value="notifications">Notifications</TabsTrigger>
|
|
60
|
+
</TabsList>
|
|
61
|
+
<TabsContent value="overview">
|
|
62
|
+
<Card>
|
|
63
|
+
<CardHeader>
|
|
64
|
+
<CardTitle>Overview</CardTitle>
|
|
65
|
+
<CardDescription>Your account overview</CardDescription>
|
|
66
|
+
</CardHeader>
|
|
67
|
+
<CardContent>
|
|
68
|
+
<p className="text-sm">View your account summary and recent activity.</p>
|
|
69
|
+
</CardContent>
|
|
70
|
+
</Card>
|
|
71
|
+
</TabsContent>
|
|
72
|
+
<TabsContent value="analytics">
|
|
73
|
+
<Card>
|
|
74
|
+
<CardHeader>
|
|
75
|
+
<CardTitle>Analytics</CardTitle>
|
|
76
|
+
<CardDescription>Performance metrics</CardDescription>
|
|
77
|
+
</CardHeader>
|
|
78
|
+
<CardContent>
|
|
79
|
+
<p className="text-sm">Track your performance and engagement.</p>
|
|
80
|
+
</CardContent>
|
|
81
|
+
</Card>
|
|
82
|
+
</TabsContent>
|
|
83
|
+
<TabsContent value="reports">
|
|
84
|
+
<Card>
|
|
85
|
+
<CardHeader>
|
|
86
|
+
<CardTitle>Reports</CardTitle>
|
|
87
|
+
<CardDescription>Generated reports</CardDescription>
|
|
88
|
+
</CardHeader>
|
|
89
|
+
<CardContent>
|
|
90
|
+
<p className="text-sm">Access your generated reports.</p>
|
|
91
|
+
</CardContent>
|
|
92
|
+
</Card>
|
|
93
|
+
</TabsContent>
|
|
94
|
+
<TabsContent value="notifications">
|
|
95
|
+
<Card>
|
|
96
|
+
<CardHeader>
|
|
97
|
+
<CardTitle>Notifications</CardTitle>
|
|
98
|
+
<CardDescription>Manage notifications</CardDescription>
|
|
99
|
+
</CardHeader>
|
|
100
|
+
<CardContent>
|
|
101
|
+
<p className="text-sm">Configure your notification preferences.</p>
|
|
102
|
+
</CardContent>
|
|
103
|
+
</Card>
|
|
104
|
+
</TabsContent>
|
|
105
|
+
</Tabs>
|
|
106
|
+
),
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const DarkMode: Story = {
|
|
110
|
+
parameters: {
|
|
111
|
+
backgrounds: { default: "dark" },
|
|
112
|
+
},
|
|
113
|
+
render: () => (
|
|
114
|
+
<div className="dark">
|
|
115
|
+
<Tabs defaultValue="account" className="w-[400px]">
|
|
116
|
+
<TabsList>
|
|
117
|
+
<TabsTrigger value="account">Account</TabsTrigger>
|
|
118
|
+
<TabsTrigger value="password">Password</TabsTrigger>
|
|
119
|
+
</TabsList>
|
|
120
|
+
<TabsContent value="account">
|
|
121
|
+
<p className="text-sm">Make changes to your account here.</p>
|
|
122
|
+
</TabsContent>
|
|
123
|
+
<TabsContent value="password">
|
|
124
|
+
<p className="text-sm">Change your password here.</p>
|
|
125
|
+
</TabsContent>
|
|
126
|
+
</Tabs>
|
|
127
|
+
</div>
|
|
128
|
+
),
|
|
129
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Tabs as ShadcnTabs,
|
|
4
|
+
TabsContent,
|
|
5
|
+
TabsList,
|
|
6
|
+
TabsTrigger,
|
|
7
|
+
} from "../../ui/tabs"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tabs Primitive
|
|
11
|
+
*
|
|
12
|
+
* A foundational tabs component for organizing content into switchable panels.
|
|
13
|
+
* Built on Radix UI Tabs primitive with WCAG 2.1 Level AA compliance.
|
|
14
|
+
*
|
|
15
|
+
* ## Accessibility Features
|
|
16
|
+
* - Arrow key navigation between tabs
|
|
17
|
+
* - Home/End keys for first/last tab
|
|
18
|
+
* - Automatic ARIA attributes (role="tablist", "tab", "tabpanel")
|
|
19
|
+
* - Focus management and keyboard support
|
|
20
|
+
* - Screen reader announcements
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <Tabs defaultValue="tab1">
|
|
25
|
+
* <TabsList>
|
|
26
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
27
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
28
|
+
* </TabsList>
|
|
29
|
+
* <TabsContent value="tab1">Content 1</TabsContent>
|
|
30
|
+
* <TabsContent value="tab2">Content 2</TabsContent>
|
|
31
|
+
* </Tabs>
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @see https://ui.shadcn.com/docs/components/tabs
|
|
35
|
+
* @see https://www.radix-ui.com/primitives/docs/components/tabs
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export type TabsProps = React.ComponentProps<typeof ShadcnTabs>
|
|
39
|
+
export type TabsListProps = React.ComponentProps<typeof TabsList>
|
|
40
|
+
export type TabsTriggerProps = React.ComponentProps<typeof TabsTrigger>
|
|
41
|
+
export type TabsContentProps = React.ComponentProps<typeof TabsContent>
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Tabs component
|
|
45
|
+
*
|
|
46
|
+
* A tabs component for organizing content into switchable panels.
|
|
47
|
+
* Built on Radix UI Tabs primitive with full accessibility support.
|
|
48
|
+
*
|
|
49
|
+
* Features:
|
|
50
|
+
* - Arrow key navigation between tabs
|
|
51
|
+
* - Home/End keys for first/last tab
|
|
52
|
+
* - Automatic ARIA attributes
|
|
53
|
+
* - Focus management
|
|
54
|
+
* - Screen reader support
|
|
55
|
+
* - Horizontal and vertical orientation
|
|
56
|
+
* - Dark mode support
|
|
57
|
+
*/
|
|
58
|
+
export const Tabs = React.forwardRef<
|
|
59
|
+
React.ElementRef<typeof ShadcnTabs>,
|
|
60
|
+
TabsProps
|
|
61
|
+
>((props, ref) => {
|
|
62
|
+
return <ShadcnTabs {...props} />
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
Tabs.displayName = "Tabs"
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Re-export Tabs sub-components for composition
|
|
69
|
+
*/
|
|
70
|
+
export { TabsContent, TabsList, TabsTrigger }
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { Textarea } from "./Textarea"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Textarea Primitive Stories
|
|
6
|
+
*
|
|
7
|
+
* The Textarea primitive provides a consistent multi-line text input experience across the application.
|
|
8
|
+
* It supports validation states, accessibility features, and automatic content-based resizing.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const meta = {
|
|
12
|
+
title: "Primitives/Textarea",
|
|
13
|
+
component: Textarea,
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: "centered",
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component:
|
|
19
|
+
"A foundational textarea component built on shadcn/ui Textarea. Supports multi-line text input, validation states, and accessibility features including ARIA attributes for error states. Features field-sizing-content for automatic height adjustment.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
tags: ["autodocs"],
|
|
24
|
+
argTypes: {
|
|
25
|
+
size: {
|
|
26
|
+
control: "select",
|
|
27
|
+
options: ["sm", "default", "lg"],
|
|
28
|
+
description: "Size variant of the textarea",
|
|
29
|
+
table: {
|
|
30
|
+
defaultValue: { summary: "default" },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
state: {
|
|
34
|
+
control: "select",
|
|
35
|
+
options: ["default", "error", "success", "warning"],
|
|
36
|
+
description: "Visual state of the textarea",
|
|
37
|
+
table: {
|
|
38
|
+
defaultValue: { summary: "default" },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
placeholder: {
|
|
42
|
+
control: "text",
|
|
43
|
+
description: "Placeholder text displayed when textarea is empty",
|
|
44
|
+
},
|
|
45
|
+
rows: {
|
|
46
|
+
control: "number",
|
|
47
|
+
description: "Number of visible text lines",
|
|
48
|
+
table: {
|
|
49
|
+
defaultValue: { summary: "undefined (auto-size)" },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
disabled: {
|
|
53
|
+
control: "boolean",
|
|
54
|
+
description: "Whether the textarea is disabled",
|
|
55
|
+
table: {
|
|
56
|
+
defaultValue: { summary: false },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
"aria-invalid": {
|
|
60
|
+
control: "boolean",
|
|
61
|
+
description: "Indicates whether the textarea value is invalid",
|
|
62
|
+
table: {
|
|
63
|
+
defaultValue: { summary: false },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
} satisfies Meta<typeof Textarea>
|
|
68
|
+
|
|
69
|
+
export default meta
|
|
70
|
+
type Story = StoryObj<typeof meta>
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Default textarea with automatic height adjustment
|
|
74
|
+
*/
|
|
75
|
+
export const Default: Story = {
|
|
76
|
+
args: {
|
|
77
|
+
placeholder: "Enter your message...",
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Textarea with fixed number of rows
|
|
83
|
+
*/
|
|
84
|
+
export const WithRows: Story = {
|
|
85
|
+
args: {
|
|
86
|
+
placeholder: "Enter description...",
|
|
87
|
+
rows: 5,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Small textarea for brief comments
|
|
93
|
+
*/
|
|
94
|
+
export const Small: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
placeholder: "Brief comment...",
|
|
97
|
+
rows: 3,
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Large textarea for longer content
|
|
103
|
+
*/
|
|
104
|
+
export const Large: Story = {
|
|
105
|
+
args: {
|
|
106
|
+
placeholder: "Enter detailed description...",
|
|
107
|
+
rows: 10,
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Disabled textarea that cannot be interacted with
|
|
113
|
+
*/
|
|
114
|
+
export const Disabled: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
placeholder: "Disabled textarea",
|
|
117
|
+
disabled: true,
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Textarea with pre-filled value
|
|
123
|
+
*/
|
|
124
|
+
export const WithValue: Story = {
|
|
125
|
+
args: {
|
|
126
|
+
defaultValue:
|
|
127
|
+
"This is some pre-filled text content.\nIt spans multiple lines.\nYou can edit this text.",
|
|
128
|
+
rows: 5,
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Invalid textarea showing error state
|
|
134
|
+
*/
|
|
135
|
+
export const Invalid: Story = {
|
|
136
|
+
args: {
|
|
137
|
+
placeholder: "Enter valid text...",
|
|
138
|
+
defaultValue: "This text contains errors",
|
|
139
|
+
"aria-invalid": true,
|
|
140
|
+
rows: 4,
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Textarea with maximum length constraint
|
|
146
|
+
*/
|
|
147
|
+
export const WithMaxLength: Story = {
|
|
148
|
+
args: {
|
|
149
|
+
placeholder: "Maximum 200 characters...",
|
|
150
|
+
maxLength: 200,
|
|
151
|
+
rows: 4,
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Read-only textarea for displaying content
|
|
157
|
+
*/
|
|
158
|
+
export const ReadOnly: Story = {
|
|
159
|
+
args: {
|
|
160
|
+
defaultValue:
|
|
161
|
+
"This is read-only content.\nIt cannot be edited but can be selected and copied.",
|
|
162
|
+
readOnly: true,
|
|
163
|
+
rows: 4,
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Small textarea size
|
|
169
|
+
*/
|
|
170
|
+
export const SmallSize: Story = {
|
|
171
|
+
args: {
|
|
172
|
+
placeholder: "Small textarea",
|
|
173
|
+
size: "sm",
|
|
174
|
+
rows: 4,
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Large textarea size
|
|
180
|
+
*/
|
|
181
|
+
export const LargeSize: Story = {
|
|
182
|
+
args: {
|
|
183
|
+
placeholder: "Large textarea",
|
|
184
|
+
size: "lg",
|
|
185
|
+
rows: 4,
|
|
186
|
+
},
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Error state textarea
|
|
191
|
+
*/
|
|
192
|
+
export const ErrorState: Story = {
|
|
193
|
+
args: {
|
|
194
|
+
placeholder: "Enter valid text...",
|
|
195
|
+
defaultValue: "This text contains errors",
|
|
196
|
+
state: "error",
|
|
197
|
+
rows: 4,
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Success state textarea
|
|
203
|
+
*/
|
|
204
|
+
export const SuccessState: Story = {
|
|
205
|
+
args: {
|
|
206
|
+
placeholder: "Enter text...",
|
|
207
|
+
defaultValue: "This text is valid",
|
|
208
|
+
state: "success",
|
|
209
|
+
rows: 4,
|
|
210
|
+
},
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Warning state textarea
|
|
215
|
+
*/
|
|
216
|
+
export const WarningState: Story = {
|
|
217
|
+
args: {
|
|
218
|
+
placeholder: "Enter text...",
|
|
219
|
+
defaultValue: "This text might need attention",
|
|
220
|
+
state: "warning",
|
|
221
|
+
rows: 4,
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Size variants showcase
|
|
227
|
+
*/
|
|
228
|
+
export const SizeVariants: Story = {
|
|
229
|
+
render: () => (
|
|
230
|
+
<div className="flex flex-col gap-4 w-96">
|
|
231
|
+
<div>
|
|
232
|
+
<label className="text-sm font-medium mb-1 block">Small</label>
|
|
233
|
+
<Textarea placeholder="Small textarea..." size="sm" rows={3} />
|
|
234
|
+
</div>
|
|
235
|
+
<div>
|
|
236
|
+
<label className="text-sm font-medium mb-1 block">Default</label>
|
|
237
|
+
<Textarea placeholder="Default textarea..." size="default" rows={3} />
|
|
238
|
+
</div>
|
|
239
|
+
<div>
|
|
240
|
+
<label className="text-sm font-medium mb-1 block">Large</label>
|
|
241
|
+
<Textarea placeholder="Large textarea..." size="lg" rows={3} />
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* State variants showcase
|
|
249
|
+
*/
|
|
250
|
+
export const StateVariants: Story = {
|
|
251
|
+
render: () => (
|
|
252
|
+
<div className="flex flex-col gap-4 w-96">
|
|
253
|
+
<div>
|
|
254
|
+
<label className="text-sm font-medium mb-1 block">Default State</label>
|
|
255
|
+
<Textarea placeholder="Default state..." state="default" rows={3} />
|
|
256
|
+
</div>
|
|
257
|
+
<div>
|
|
258
|
+
<label className="text-sm font-medium mb-1 block">Error State</label>
|
|
259
|
+
<Textarea placeholder="Error state..." state="error" defaultValue="Invalid content" rows={3} />
|
|
260
|
+
</div>
|
|
261
|
+
<div>
|
|
262
|
+
<label className="text-sm font-medium mb-1 block">Success State</label>
|
|
263
|
+
<Textarea placeholder="Success state..." state="success" defaultValue="Valid content" rows={3} />
|
|
264
|
+
</div>
|
|
265
|
+
<div>
|
|
266
|
+
<label className="text-sm font-medium mb-1 block">Warning State</label>
|
|
267
|
+
<Textarea placeholder="Warning state..." state="warning" defaultValue="Needs attention" rows={3} />
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
),
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Combined variants showcase
|
|
275
|
+
*/
|
|
276
|
+
export const CombinedVariants: Story = {
|
|
277
|
+
render: () => (
|
|
278
|
+
<div className="flex flex-col gap-4 w-96">
|
|
279
|
+
<div>
|
|
280
|
+
<label className="text-sm font-medium mb-1 block">Small Error</label>
|
|
281
|
+
<Textarea placeholder="Small error..." size="sm" state="error" rows={3} />
|
|
282
|
+
</div>
|
|
283
|
+
<div>
|
|
284
|
+
<label className="text-sm font-medium mb-1 block">Default Success</label>
|
|
285
|
+
<Textarea placeholder="Default success..." size="default" state="success" rows={3} />
|
|
286
|
+
</div>
|
|
287
|
+
<div>
|
|
288
|
+
<label className="text-sm font-medium mb-1 block">Large Warning</label>
|
|
289
|
+
<Textarea placeholder="Large warning..." size="lg" state="warning" rows={3} />
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
),
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* All textarea variants and states showcased together
|
|
297
|
+
*/
|
|
298
|
+
export const AllVariants: Story = {
|
|
299
|
+
render: () => (
|
|
300
|
+
<div className="flex flex-col gap-4 w-96">
|
|
301
|
+
<div>
|
|
302
|
+
<label className="text-sm font-medium mb-1 block">Default (Auto-size)</label>
|
|
303
|
+
<Textarea placeholder="Enter your message..." />
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<div>
|
|
307
|
+
<label className="text-sm font-medium mb-1 block">Small (3 rows)</label>
|
|
308
|
+
<Textarea placeholder="Brief comment..." rows={3} />
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<div>
|
|
312
|
+
<label className="text-sm font-medium mb-1 block">Medium (5 rows)</label>
|
|
313
|
+
<Textarea placeholder="Enter description..." rows={5} />
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
<div>
|
|
317
|
+
<label className="text-sm font-medium mb-1 block">With Value</label>
|
|
318
|
+
<Textarea
|
|
319
|
+
defaultValue="This is some pre-filled text content. It spans multiple lines. You can edit this text."
|
|
320
|
+
rows={4}
|
|
321
|
+
/>
|
|
322
|
+
</div>
|
|
323
|
+
|
|
324
|
+
<div>
|
|
325
|
+
<label className="text-sm font-medium mb-1 block">Disabled</label>
|
|
326
|
+
<Textarea placeholder="Disabled textarea" disabled rows={3} />
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<div>
|
|
330
|
+
<label className="text-sm font-medium mb-1 block">Invalid</label>
|
|
331
|
+
<Textarea
|
|
332
|
+
placeholder="Enter valid text..."
|
|
333
|
+
defaultValue="This text contains errors"
|
|
334
|
+
aria-invalid
|
|
335
|
+
rows={3}
|
|
336
|
+
/>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<div>
|
|
340
|
+
<label className="text-sm font-medium mb-1 block">With Max Length (200)</label>
|
|
341
|
+
<Textarea
|
|
342
|
+
placeholder="Maximum 200 characters..."
|
|
343
|
+
maxLength={200}
|
|
344
|
+
rows={3}
|
|
345
|
+
/>
|
|
346
|
+
</div>
|
|
347
|
+
|
|
348
|
+
<div>
|
|
349
|
+
<label className="text-sm font-medium mb-1 block">Read Only</label>
|
|
350
|
+
<Textarea
|
|
351
|
+
defaultValue="This is read-only content. It cannot be edited but can be selected and copied."
|
|
352
|
+
readOnly
|
|
353
|
+
rows={3}
|
|
354
|
+
/>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
),
|
|
358
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Textarea as ShadcnTextarea,
|
|
4
|
+
textareaVariants,
|
|
5
|
+
} from "../../ui/textarea"
|
|
6
|
+
import type { VariantProps } from "class-variance-authority"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Textarea Primitive
|
|
10
|
+
*
|
|
11
|
+
* A foundational textarea component that wraps shadcn/ui Textarea with design system
|
|
12
|
+
* enhancements. This primitive serves as the single source of truth for all multi-line
|
|
13
|
+
* text input interactions across the application.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Textarea placeholder="Enter your message..." />
|
|
18
|
+
*
|
|
19
|
+
* <Textarea
|
|
20
|
+
* placeholder="Description"
|
|
21
|
+
* rows={5}
|
|
22
|
+
* size="sm"
|
|
23
|
+
* />
|
|
24
|
+
*
|
|
25
|
+
* <Textarea
|
|
26
|
+
* placeholder="Enter comment"
|
|
27
|
+
* state="error"
|
|
28
|
+
* />
|
|
29
|
+
*
|
|
30
|
+
* <Textarea
|
|
31
|
+
* placeholder="Success state"
|
|
32
|
+
* state="success"
|
|
33
|
+
* size="lg"
|
|
34
|
+
* />
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @see https://ui.shadcn.com/docs/components/textarea - shadcn/ui Textarea documentation
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Textarea component props
|
|
42
|
+
* Extends the native textarea element props with variant options
|
|
43
|
+
*/
|
|
44
|
+
export type TextareaProps = React.ComponentProps<"textarea"> &
|
|
45
|
+
VariantProps<typeof textareaVariants>
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Textarea component
|
|
49
|
+
*
|
|
50
|
+
* A versatile multi-line text input component built on shadcn/ui foundation.
|
|
51
|
+
* Optimized with React.memo for performance in high-frequency rendering scenarios.
|
|
52
|
+
*
|
|
53
|
+
* Features:
|
|
54
|
+
* - Full WCAG 2.1 Level AA compliance
|
|
55
|
+
* - Size variants (sm, default, lg) for different contexts
|
|
56
|
+
* - State variants (default, error, success, warning) for visual feedback
|
|
57
|
+
* - Customizable row height
|
|
58
|
+
* - Validation state styling via aria-invalid
|
|
59
|
+
* - Dark mode support
|
|
60
|
+
* - Placeholder and disabled states
|
|
61
|
+
* - Auto-resize capabilities
|
|
62
|
+
*/
|
|
63
|
+
export const Textarea = React.memo(
|
|
64
|
+
React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
65
|
+
(props, ref) => {
|
|
66
|
+
return <ShadcnTextarea ref={ref} {...props} />
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
Textarea.displayName = "Textarea"
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Re-export textareaVariants for consumers who need direct access to the variant generator.
|
|
75
|
+
* This is useful for creating custom textarea-like components that need consistent styling.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* import { textareaVariants } from './Textarea'
|
|
80
|
+
*
|
|
81
|
+
* <div className={textareaVariants({ size: "sm", state: "error" })}>
|
|
82
|
+
* Custom textarea-like div
|
|
83
|
+
* </div>
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export { textareaVariants }
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Re-export VariantProps for type inference in consuming components
|
|
90
|
+
*/
|
|
91
|
+
export type { VariantProps }
|