aural-ui 4.0.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +8 -1
  2. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
  3. package/dist/components/avatar/Avatar.stories.tsx +219 -235
  4. package/dist/components/badge/Badge.stories.tsx +379 -116
  5. package/dist/components/banner/Banner.stories.tsx +445 -391
  6. package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
  7. package/dist/components/button/Button.stories.tsx +585 -230
  8. package/dist/components/card/Card.stories.tsx +619 -301
  9. package/dist/components/char-count/CharCount.stories.tsx +350 -248
  10. package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
  11. package/dist/components/chip/Chip.stories.tsx +362 -168
  12. package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
  13. package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
  14. package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
  15. package/dist/components/command/Command.stories.tsx +530 -867
  16. package/dist/components/dialog/Dialog.stories.tsx +501 -950
  17. package/dist/components/divider/Divider.stories.tsx +264 -527
  18. package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
  19. package/dist/components/drawer/Drawer.stories.tsx +659 -1023
  20. package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
  21. package/dist/components/form/Form.stories.tsx +560 -274
  22. package/dist/components/helper-text/HelperText.stories.tsx +199 -200
  23. package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
  24. package/dist/components/icon-button/IconButton.stories.tsx +837 -194
  25. package/dist/components/if-else/if-else.stories.tsx +370 -83
  26. package/dist/components/input/Input.stories.tsx +436 -368
  27. package/dist/components/label/Label.stories.tsx +156 -154
  28. package/dist/components/list/List.stories.tsx +484 -835
  29. package/dist/components/marquee/Marquee.stories.tsx +356 -712
  30. package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
  31. package/dist/components/overlay/Overlay.stories.tsx +452 -824
  32. package/dist/components/pagination/Pagination.stories.tsx +721 -210
  33. package/dist/components/popover/Popover.stories.tsx +481 -896
  34. package/dist/components/radio/Radio.stories.tsx +432 -124
  35. package/dist/components/resizable/Resizable.stories.tsx +495 -799
  36. package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
  37. package/dist/components/search/Search.stories.tsx +312 -595
  38. package/dist/components/select/Select.stories.tsx +684 -789
  39. package/dist/components/sheet/Sheet.stories.tsx +671 -950
  40. package/dist/components/skelton/Skelton.stories.tsx +230 -764
  41. package/dist/components/slider/Slider.stories.tsx +383 -760
  42. package/dist/components/stepper/Stepper.stories.tsx +371 -514
  43. package/dist/components/switch/Switch.stories.tsx +461 -208
  44. package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
  45. package/dist/components/table/Table.stories.tsx +770 -916
  46. package/dist/components/tabs/Tabs.stories.tsx +458 -1455
  47. package/dist/components/tag/Tag.stories.tsx +714 -542
  48. package/dist/components/textarea/TextArea.stories.tsx +621 -562
  49. package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
  50. package/dist/components/toast/Toast.stories.tsx +452 -1339
  51. package/dist/components/toggle/Toggle.stories.tsx +488 -931
  52. package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
  53. package/dist/components/typography/Typography.stories.tsx +406 -89
  54. package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
  55. package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
  56. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
  57. package/dist/icons/Icons.stories.tsx +0 -12
  58. package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
  59. package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
  60. package/dist/icons/all-icons.tsx +37 -16
  61. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
  62. package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
  63. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
  64. package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
  65. package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
  66. package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
  67. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
  68. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
  69. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
  70. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
  71. package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
  72. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
  73. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
  74. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
  75. package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
  76. package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
  77. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
  78. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
  79. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
  80. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
  81. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
  82. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
  83. package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
  84. package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
  85. package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
  86. package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
  87. package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
  88. package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
  89. package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
  90. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
  91. package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
  92. package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
  93. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
  94. package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
  95. package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
  96. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
  97. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
  98. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
  99. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
  100. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
  101. package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
  102. package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
  103. package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
  104. package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
  105. package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
  106. package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
  107. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
  108. package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
  109. package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
  110. package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
  111. package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
  112. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
  113. package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
  114. package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
  115. package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
  116. package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
  117. package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
  118. package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
  119. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
  120. package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
  121. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
  122. package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
  123. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
  124. package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
  125. package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
  126. package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
  127. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
  128. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
  129. package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
  130. package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
  131. package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
  132. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
  133. package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
  134. package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
  135. package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
  136. package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
  137. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
  138. package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
  139. package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
  140. package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
  141. package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
  142. package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
  143. package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
  144. package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
  145. package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
  146. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
  147. package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
  148. package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
  149. package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
  150. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
  151. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
  152. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
  153. package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
  154. package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
  155. package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
  156. package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
  157. package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
  158. package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
  159. package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
  160. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
  161. package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
  162. package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
  163. package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
  164. package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
  165. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
  166. package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
  167. package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
  168. package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
  169. package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
  170. package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
  171. package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
  172. package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
  173. package/dist/index.cjs +90 -90
  174. package/dist/index.js +90 -90
  175. package/package.json +8 -3
@@ -4,18 +4,16 @@ import { Button } from "@components/button"
4
4
  import { Checkbox } from "@components/checkbox"
5
5
  import Input from "@components/input"
6
6
  import { Label } from "@components/label"
7
- import {
8
- Select,
9
- SelectContent,
10
- SelectItem,
11
- SelectTrigger,
12
- SelectValue,
13
- } from "@components/select"
14
- import Textarea from "@components/textarea"
15
- import { CrossIcon } from "@icons/cross-icon"
16
- import { EditBigIcon } from "@icons/edit-big-icon"
7
+ import { ChevronRightIcon } from "@icons/chevron-right-icon"
8
+ import { MaintenanceIcon } from "@icons/maintenance-icon"
9
+ import { MusicalNoteIcon } from "@icons/musical-note-icon"
10
+ import { SearchIcon } from "@icons/search-icon"
11
+ import { SiteLogoIcon } from "@icons/site-logo-icon"
12
+ import { TickCircleIcon } from "@icons/tick-circle-icon"
17
13
  import type { Meta, StoryObj } from "@storybook/react-vite"
18
14
 
15
+ import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
16
+
19
17
  import {
20
18
  Drawer,
21
19
  DrawerClose,
@@ -27,194 +25,50 @@ import {
27
25
  DrawerTrigger,
28
26
  } from "."
29
27
 
30
- const meta: Meta<typeof DrawerContent> = {
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ const meta: Meta<any> = {
31
30
  title: "Components/UI/Drawer",
32
31
  component: Drawer,
33
32
  parameters: {
34
33
  layout: "centered",
35
- backgrounds: {
36
- default: "dark",
37
- values: [
38
- { name: "dark", value: "#0a0a0a" },
39
- { name: "light", value: "#ffffff" },
40
- ],
41
- },
42
34
  docs: {
43
35
  description: {
44
- component: `
45
- # Drawer Component
46
-
47
- A slide-out drawer component built on Vaul primitives with support for multiple directions, smooth animations, customizable content sections, and enhanced accessibility features.
48
-
49
- ## Features
50
-
51
- - **Multiple Directions**: Top, bottom, left, and right slide directions
52
- - **Multiple Variants**: Neutral and gradient styles with custom styling
53
- - **Custom Overlays**: Configurable opacity, glass effect, and noise texture
54
- - **Smooth Animations**: Fade in/out animations for overlay and content with customizable duration
55
- - **Accessible**: Full keyboard navigation, screen reader support, and focus management
56
- - **Flexible Content**: Header, footer, and body sections with custom styling
57
- - **Portal Rendering**: Renders outside normal DOM hierarchy for proper layering
58
- - **Focus Management**: Automatic focus trapping and restoration
59
- - **Responsive Design**: Adapts to different screen sizes with mobile-first approach
60
- - **Drag Support**: Built-in drag gestures for intuitive interaction
61
- - **Nested Support**: Support for nested drawers with proper z-index management
62
-
63
- ## Directions
64
-
65
- The drawer can slide from different directions using the \`direction\` prop:
66
-
67
- - **Bottom** (default): Slides up from the bottom - ideal for mobile navigation
68
- - **Top**: Slides down from the top - useful for notifications or quick actions
69
- - **Left**: Slides in from the left - perfect for navigation menus
70
- - **Right**: Slides in from the right - great for settings or detail panels
71
-
72
- ## Usage Examples
73
-
74
- ### Basic Drawer with Direction Configuration
75
- \`\`\`tsx
76
- import { Drawer, DrawerContent, DrawerTrigger } from '@/components/drawer'
77
-
78
- // Bottom drawer (default)
79
- <Drawer>
80
- <DrawerTrigger asChild>
81
- <Button>Open Bottom Drawer</Button>
82
- </DrawerTrigger>
83
- <DrawerContent>
84
- Content slides up from bottom
85
- </DrawerContent>
86
- </Drawer>
87
-
88
- // Top drawer
89
- <Drawer>
90
- <DrawerTrigger asChild>
91
- <Button>Open Top Drawer</Button>
92
- </DrawerTrigger>
93
- <DrawerContent>
94
- Content slides down from top
95
- </DrawerContent>
96
- </Drawer>
97
-
98
- // Left drawer
99
- <Drawer>
100
- <DrawerTrigger asChild>
101
- <Button>Open Left Drawer</Button>
102
- </DrawerTrigger>
103
- <DrawerContent>
104
- Content slides in from left
105
- </DrawerContent>
106
- </Drawer>
107
-
108
- // Right drawer
109
- <Drawer>
110
- <DrawerTrigger asChild>
111
- <Button>Open Right Drawer</Button>
112
- </DrawerTrigger>
113
- <DrawerContent>
114
- Content slides in from right
115
- </DrawerContent>
116
- </Drawer>
117
-
118
- ### Drawer with Custom Overlay Effects
119
- \`\`\`tsx
120
- <Drawer>
121
- <DrawerTrigger asChild>
122
- <Button>Open Drawer with Custom Overlay</Button>
123
- </DrawerTrigger>
124
- <DrawerContent
125
- noise="high"
126
- opacity="medium"
127
- glass="low"
128
- >
129
- Content with custom overlay effects
130
- </DrawerContent>
131
- </Drawer>
132
- \`\`\`
133
-
134
- ### Overlay Configuration
135
-
136
- The drawer supports configurable overlay effects through the \`opacity\`, \`glass\`, and \`noise\` props:
137
-
138
- - **opacity**: Controls background dimming level
139
- - \`"high"\` - Strong dimming (80%)
140
- - \`"medium"\` - Balanced dimming (60%) - default
141
- - \`"low"\` - Subtle dimming (40%)
142
- - \`"none"\` - No dimming (100% coverage)
143
-
144
- - **glass**: Controls backdrop blur effect
145
- - \`"high"\` - Strong blur effect
146
- - \`"medium"\` - Balanced blur effect
147
- - \`"low"\` - Subtle blur effect - default
148
- - \`"none"\` - No blur effect
149
-
150
- - **noise**: Controls texture overlay
151
- - \`"high"\` - Strong texture pattern
152
- - \`"medium"\` - Balanced texture pattern
153
- - \`"low"\` - Subtle texture pattern - default
154
- - \`"none"\` - No texture pattern
155
-
156
- ### Usage Examples
157
-
158
- \`\`\`tsx
159
- // High opacity with glass effect
160
- <DrawerContent opacity="high" glass="medium" noise="low">
161
- Content with strong background dimming
162
- </DrawerContent>
163
-
164
- // Subtle overlay with texture
165
- <DrawerContent opacity="low" glass="none" noise="high">
166
- Content with subtle dimming and strong texture
167
- </DrawerContent>
168
-
169
- // No overlay effects
170
- <DrawerContent opacity="none" glass="none" noise="none">
171
- Content without any overlay effects
172
- </DrawerContent>
173
- \`\`\`
174
- \`\`\`
175
-
176
- ### Drawer with Form Elements
177
- \`\`\`tsx
178
- <Drawer>
179
- <DrawerTrigger asChild>
180
- <Button>Open Form Drawer</Button>
181
- </DrawerTrigger>
182
- <DrawerContent>
183
- <DrawerHeader>
184
- <DrawerTitle>Contact Form</DrawerTitle>
185
- <DrawerDescription>Fill out the form below to get in touch.</DrawerDescription>
186
- </DrawerHeader>
187
- <div className="space-y-4 p-4">
188
- <Input placeholder="Name" />
189
- <Input placeholder="Email" type="email" />
190
- <Textarea placeholder="Message" rows={4} />
191
- </div>
192
- <DrawerFooter>
193
- <Button>Submit</Button>
194
- <DrawerClose asChild>
195
- <Button variant="outline">Cancel</Button>
196
- </DrawerClose>
197
- </DrawerFooter>
198
- </DrawerContent>
199
- </Drawer>
200
- \`\`\`
201
- `,
36
+ component:
37
+ "A slide-out drawer built on Vaul primitives. Supports four slide directions, neutral and gradient variants, configurable glass/noise overlays, an optional swipe handle, and an optional backdrop overlay — ideal for mobile navigation, settings panels, and contextual actions.",
202
38
  },
39
+ page: () => (
40
+ <AuralComponentDocsPage
41
+ features={[
42
+ {
43
+ title: "4 Slide Directions",
44
+ description: "Top, bottom, left, right",
45
+ },
46
+ {
47
+ title: "Glass & Noise Overlay",
48
+ description: "Blur and grain levels",
49
+ },
50
+ {
51
+ title: "Swipe Handle",
52
+ description: "Optional pill indicator",
53
+ },
54
+ ]}
55
+ />
56
+ ),
203
57
  },
204
58
  },
205
59
  argTypes: {
206
60
  variant: {
207
61
  control: { type: "select" },
208
62
  options: ["neutral", "gradient"],
209
- description: "Drawer variant for different use cases",
63
+ description: "Visual style variant",
210
64
  },
211
65
  showOverlay: {
212
66
  control: { type: "boolean" },
213
- description: "Whether to show the overlay backdrop",
67
+ description: "Whether to render the backdrop overlay",
214
68
  },
215
69
  showSwipeButton: {
216
70
  control: { type: "boolean" },
217
- description: "Whether to show the swipe indicator button",
71
+ description: "Show swipe indicator handle (bottom drawers only)",
218
72
  },
219
73
  opacity: {
220
74
  control: { type: "select" },
@@ -224,12 +78,12 @@ The drawer supports configurable overlay effects through the \`opacity\`, \`glas
224
78
  glass: {
225
79
  control: { type: "select" },
226
80
  options: ["high", "medium", "low", "none"],
227
- description: "Overlay glass effect level",
81
+ description: "Overlay glass blur intensity",
228
82
  },
229
83
  noise: {
230
84
  control: { type: "select" },
231
85
  options: ["high", "medium", "low", "none"],
232
- description: "Overlay noise texture level",
86
+ description: "Overlay noise texture intensity",
233
87
  },
234
88
  },
235
89
  tags: ["autodocs"],
@@ -238,36 +92,28 @@ The drawer supports configurable overlay effects through the \`opacity\`, \`glas
238
92
  export default meta
239
93
  type Story = StoryObj<typeof Drawer>
240
94
 
241
- // 1. Direction Examples
242
- export const DirectionExamples: Story = {
95
+ // ─── Configurations ────────────────────────────────────────────────────────────
96
+
97
+ export const Configurations: Story = {
243
98
  render: () => {
244
- const DirectionDrawer = ({ direction, title, description }: any) => {
245
- return (
99
+ const DirDrawer = ({ direction, label, description }: any) => (
100
+ <div className="space-y-2 text-center">
246
101
  <Drawer direction={direction}>
247
102
  <DrawerTrigger asChild>
248
103
  <Button variant="outline" size="sm">
249
- {title}
104
+ {label}
250
105
  </Button>
251
106
  </DrawerTrigger>
252
107
  <DrawerContent>
253
108
  <DrawerHeader>
254
- <DrawerTitle>{title}</DrawerTitle>
109
+ <DrawerTitle>{label} Drawer</DrawerTitle>
255
110
  <DrawerDescription>{description}</DrawerDescription>
256
111
  </DrawerHeader>
257
- <div className="p-2 py-4">
258
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
259
- <div className="text-fm-primary/60 space-y-1 text-xs">
260
- <div>
261
- Direction:{" "}
262
- <span className="text-fm-primary">{direction}</span>
263
- </div>
264
- <div>
265
- Content:{" "}
266
- <span className="text-fm-primary">
267
- Slides from {direction}
268
- </span>
269
- </div>
270
- </div>
112
+ <div className="p-4">
113
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
114
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
115
+ direction="{direction}"
116
+ </code>
271
117
  </div>
272
118
  </div>
273
119
  <DrawerFooter>
@@ -277,77 +123,202 @@ export const DirectionExamples: Story = {
277
123
  </DrawerFooter>
278
124
  </DrawerContent>
279
125
  </Drawer>
280
- )
281
- }
126
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
127
+ {label}
128
+ </p>
129
+ </div>
130
+ )
131
+
132
+ const OverlayDrawer = ({ label, opacity, glass, noise }: any) => (
133
+ <div className="space-y-2 text-center">
134
+ <Drawer direction="bottom">
135
+ <DrawerTrigger asChild>
136
+ <Button variant="outline" size="sm">
137
+ {label}
138
+ </Button>
139
+ </DrawerTrigger>
140
+ <DrawerContent opacity={opacity} glass={glass} noise={noise}>
141
+ <DrawerHeader>
142
+ <DrawerTitle>{label}</DrawerTitle>
143
+ <DrawerDescription>Overlay configuration demo.</DrawerDescription>
144
+ </DrawerHeader>
145
+ <div className="p-4">
146
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
147
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
148
+ {opacity ? `opacity="${opacity}"` : ""}
149
+ {glass ? ` glass="${glass}"` : ""}
150
+ {noise ? ` noise="${noise}"` : ""}
151
+ </code>
152
+ </div>
153
+ </div>
154
+ <DrawerFooter>
155
+ <DrawerClose asChild>
156
+ <Button>Close</Button>
157
+ </DrawerClose>
158
+ </DrawerFooter>
159
+ </DrawerContent>
160
+ </Drawer>
161
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
162
+ {label}
163
+ </p>
164
+ </div>
165
+ )
282
166
 
283
167
  return (
284
168
  <div className="space-y-8">
285
- <div className="text-center">
286
- <h3 className="text-fm-primary mb-2 font-medium">
287
- Drawer Directions
288
- </h3>
289
- <p className="text-fm-primary/60 text-sm">
290
- Explore different slide directions for various use cases
291
- </p>
169
+ {/* All four directions */}
170
+ <div className="space-y-3">
171
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
172
+ Slide Directions
173
+ </h4>
174
+ <div className="flex flex-wrap gap-6">
175
+ <DirDrawer
176
+ direction="bottom"
177
+ label="Bottom"
178
+ description="Slides up from the bottom — default for mobile."
179
+ />
180
+ <DirDrawer
181
+ direction="top"
182
+ label="Top"
183
+ description="Slides down from the top — ideal for notifications."
184
+ />
185
+ <DirDrawer
186
+ direction="left"
187
+ label="Left"
188
+ description="Slides in from the left — navigation menus."
189
+ />
190
+ <DirDrawer
191
+ direction="right"
192
+ label="Right"
193
+ description="Slides in from the right — settings panels."
194
+ />
195
+ </div>
292
196
  </div>
293
197
 
294
- <div className="space-y-6">
295
- {/* Bottom Direction */}
296
- <div className="space-y-4">
297
- <h4 className="text-fm-primary/80 text-sm font-medium">
298
- Bottom Direction (Default)
299
- </h4>
300
- <div className="flex flex-wrap gap-2">
301
- <DirectionDrawer
302
- direction="bottom"
303
- title="Bottom Drawer"
304
- description="Slides up from the bottom - ideal for mobile navigation"
305
- />
198
+ {/* Variant styles */}
199
+ <div className="space-y-3">
200
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
201
+ Variant Styles
202
+ </h4>
203
+ <div className="flex flex-wrap gap-6">
204
+ <div className="space-y-2 text-center">
205
+ <Drawer direction="bottom">
206
+ <DrawerTrigger asChild>
207
+ <Button variant="outline" size="sm">
208
+ Neutral
209
+ </Button>
210
+ </DrawerTrigger>
211
+ <DrawerContent variant="neutral">
212
+ <DrawerHeader>
213
+ <DrawerTitle>Neutral Variant</DrawerTitle>
214
+ <DrawerDescription>
215
+ Frosted glass surface with backdrop blur.
216
+ </DrawerDescription>
217
+ </DrawerHeader>
218
+ <DrawerFooter>
219
+ <DrawerClose asChild>
220
+ <Button>Close</Button>
221
+ </DrawerClose>
222
+ </DrawerFooter>
223
+ </DrawerContent>
224
+ </Drawer>
225
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
226
+ Neutral
227
+ </p>
306
228
  </div>
307
- </div>
308
229
 
309
- {/* Top Direction */}
310
- <div className="space-y-4">
311
- <h4 className="text-fm-primary/80 text-sm font-medium">
312
- Top Direction
313
- </h4>
314
- <div className="flex flex-wrap gap-2">
315
- <DirectionDrawer
316
- direction="top"
317
- title="Top Drawer"
318
- description="Slides down from the top - useful for notifications"
319
- />
230
+ <div className="space-y-2 text-center">
231
+ <Drawer direction="bottom">
232
+ <DrawerTrigger asChild>
233
+ <Button variant="outline" size="sm">
234
+ Gradient
235
+ </Button>
236
+ </DrawerTrigger>
237
+ <DrawerContent variant="gradient">
238
+ <DrawerHeader>
239
+ <DrawerTitle>Gradient Variant</DrawerTitle>
240
+ <DrawerDescription>
241
+ Surface primary with a white gradient overlay.
242
+ </DrawerDescription>
243
+ </DrawerHeader>
244
+ <DrawerFooter>
245
+ <DrawerClose asChild>
246
+ <Button>Close</Button>
247
+ </DrawerClose>
248
+ </DrawerFooter>
249
+ </DrawerContent>
250
+ </Drawer>
251
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
252
+ Gradient
253
+ </p>
320
254
  </div>
321
- </div>
322
255
 
323
- {/* Left Direction */}
324
- <div className="space-y-4">
325
- <h4 className="text-fm-primary/80 text-sm font-medium">
326
- Left Direction
327
- </h4>
328
- <div className="flex flex-wrap gap-2">
329
- <DirectionDrawer
330
- direction="left"
331
- title="Left Drawer"
332
- description="Slides in from the left - perfect for navigation menus"
333
- />
256
+ <div className="space-y-2 text-center">
257
+ <Drawer direction="bottom">
258
+ <DrawerTrigger asChild>
259
+ <Button variant="outline" size="sm">
260
+ Swipe handle
261
+ </Button>
262
+ </DrawerTrigger>
263
+ <DrawerContent showSwipeButton>
264
+ <DrawerHeader>
265
+ <DrawerTitle>Swipe Handle</DrawerTitle>
266
+ <DrawerDescription>
267
+ Pill handle appears at the top of bottom drawers.
268
+ </DrawerDescription>
269
+ </DrawerHeader>
270
+ <DrawerFooter>
271
+ <DrawerClose asChild>
272
+ <Button>Close</Button>
273
+ </DrawerClose>
274
+ </DrawerFooter>
275
+ </DrawerContent>
276
+ </Drawer>
277
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
278
+ Swipe button
279
+ </p>
334
280
  </div>
335
- </div>
336
281
 
337
- {/* Right Direction */}
338
- <div className="space-y-4">
339
- <h4 className="text-fm-primary/80 text-sm font-medium">
340
- Right Direction
341
- </h4>
342
- <div className="flex flex-wrap gap-2">
343
- <DirectionDrawer
344
- direction="right"
345
- title="Right Drawer"
346
- description="Slides in from the right - great for settings panels"
347
- />
282
+ <div className="space-y-2 text-center">
283
+ <Drawer direction="bottom">
284
+ <DrawerTrigger asChild>
285
+ <Button variant="outline" size="sm">
286
+ No overlay
287
+ </Button>
288
+ </DrawerTrigger>
289
+ <DrawerContent showOverlay={false}>
290
+ <DrawerHeader>
291
+ <DrawerTitle>No Overlay</DrawerTitle>
292
+ <DrawerDescription>
293
+ Drawer without the backdrop overlay.
294
+ </DrawerDescription>
295
+ </DrawerHeader>
296
+ <DrawerFooter>
297
+ <DrawerClose asChild>
298
+ <Button>Close</Button>
299
+ </DrawerClose>
300
+ </DrawerFooter>
301
+ </DrawerContent>
302
+ </Drawer>
303
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
304
+ No overlay
305
+ </p>
348
306
  </div>
349
307
  </div>
350
308
  </div>
309
+
310
+ {/* Glass / noise options */}
311
+ <div className="space-y-3">
312
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
313
+ Glass &amp; Noise Overlay Options
314
+ </h4>
315
+ <div className="flex flex-wrap gap-6">
316
+ <OverlayDrawer label="Low opacity" opacity="low" />
317
+ <OverlayDrawer label="High opacity" opacity="high" />
318
+ <OverlayDrawer label="High glass" glass="high" />
319
+ <OverlayDrawer label="Noise texture" noise="medium" />
320
+ </div>
321
+ </div>
351
322
  </div>
352
323
  )
353
324
  },
@@ -355,614 +326,456 @@ export const DirectionExamples: Story = {
355
326
  docs: {
356
327
  description: {
357
328
  story:
358
- "Comprehensive showcase of all drawer direction options with descriptions of their use cases.",
329
+ "Comparison of all four slide directions, both visual variants, swipe handle, overlay toggle, and glass/noise overlay options.",
359
330
  },
360
331
  },
361
332
  },
362
333
  }
363
334
 
364
- // 6. Basic Drawer
365
- export const Basic: Story = {
366
- render: () => (
367
- <Drawer>
368
- <DrawerTrigger asChild>
369
- <Button>Open Drawer</Button>
370
- </DrawerTrigger>
371
- <DrawerContent>
372
- <DrawerHeader>
373
- <DrawerTitle>Basic Drawer</DrawerTitle>
374
- <DrawerDescription>
375
- This is a basic drawer example with header, content, and footer.
376
- </DrawerDescription>
377
- </DrawerHeader>
378
- <p className="p-4 text-sm">
379
- This is the main content area of the drawer. You can put any content
380
- here.
381
- </p>
382
- <DrawerFooter>
383
- <Button>Save Changes</Button>
384
- <DrawerClose asChild>
385
- <Button variant="outline">Cancel</Button>
386
- </DrawerClose>
387
- </DrawerFooter>
388
- </DrawerContent>
389
- </Drawer>
390
- ),
391
- parameters: {
392
- docs: {
393
- description: {
394
- story:
395
- "Basic drawer example demonstrating the fundamental structure with header, content, and footer sections.",
396
- },
397
- },
398
- },
399
- }
400
- // 2. Form Drawer with Select Components
401
- export const FormDrawer: Story = {
335
+ // ─── Interactive ───────────────────────────────────────────────────────────────
336
+
337
+ export const Interactive: Story = {
402
338
  render: () => {
403
- const [formData, setFormData] = useState({
404
- name: "",
405
- email: "",
406
- category: "",
407
- priority: "",
408
- message: "",
409
- newsletter: false,
410
- })
339
+ const InteractiveDemo = () => {
340
+ const [direction, setDirection] = useState<
341
+ "top" | "bottom" | "left" | "right"
342
+ >("bottom")
343
+ const [variant, setVariant] = useState<"neutral" | "gradient">("neutral")
344
+ const [opacity, setOpacity] = useState<
345
+ "high" | "medium" | "low" | "none"
346
+ >("medium")
347
+ const [glass, setGlass] = useState<"high" | "medium" | "low" | "none">(
348
+ "none"
349
+ )
350
+ const [noise, setNoise] = useState<"high" | "medium" | "low" | "none">(
351
+ "none"
352
+ )
353
+ const [showSwipeButton, setShowSwipeButton] = useState(false)
354
+ const [name, setName] = useState("")
355
+ const [email, setEmail] = useState("")
356
+ const [submitted, setSubmitted] = useState(false)
357
+
358
+ const directions = ["bottom", "top", "left", "right"] as const
359
+ const variants = ["neutral", "gradient"] as const
360
+ const levels = ["none", "low", "medium", "high"] as const
361
+
362
+ const btnCls = (active: boolean) =>
363
+ `font-fm-text text-fm-sm leading-fm-sm rounded px-2 py-1 outline-none transition-colors ${
364
+ active
365
+ ? "bg-fm-surface-contrast text-fm-contrast"
366
+ : "bg-fm-surface-secondary text-fm-secondary hover:text-fm-primary"
367
+ }`
411
368
 
412
- const handleSubmit = (e: React.FormEvent) => {
413
- e.preventDefault()
414
- console.log("Form submitted:", formData)
415
- }
369
+ return (
370
+ <div className="w-full p-8">
371
+ <div className="mx-auto max-w-3xl space-y-6">
372
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
373
+ {/* Controls panel */}
374
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
375
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
376
+ Configuration
377
+ </p>
378
+
379
+ <div className="space-y-2">
380
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
381
+ Direction
382
+ </p>
383
+ <div className="flex flex-wrap gap-1">
384
+ {directions.map((d) => (
385
+ <button
386
+ key={d}
387
+ onClick={() => setDirection(d)}
388
+ className={btnCls(direction === d)}
389
+ >
390
+ {d}
391
+ </button>
392
+ ))}
393
+ </div>
394
+ </div>
416
395
 
417
- return (
418
- <Drawer>
419
- <DrawerTrigger asChild>
420
- <Button className="gap-2">
421
- <EditBigIcon className="h-4 w-4" />
422
- Contact Form
423
- </Button>
424
- </DrawerTrigger>
425
- <DrawerContent>
426
- <DrawerHeader>
427
- <DrawerTitle>Contact Form</DrawerTitle>
428
- <DrawerDescription>
429
- Fill out the form below to get in touch with us.
430
- </DrawerDescription>
431
- </DrawerHeader>
432
- <form onSubmit={handleSubmit} className="space-y-4 overflow-auto p-4">
433
- <div className="space-y-2">
434
- <Label htmlFor="name">Name</Label>
435
- <Input
436
- id="name"
437
- value={formData.name}
438
- onChange={(e) =>
439
- setFormData({ ...formData, name: e.target.value })
440
- }
441
- placeholder="Enter your name"
442
- />
443
- </div>
444
- <div className="space-y-2">
445
- <Label htmlFor="email">Email</Label>
446
- <Input
447
- id="email"
448
- type="email"
449
- value={formData.email}
450
- onChange={(e) =>
451
- setFormData({ ...formData, email: e.target.value })
452
- }
453
- placeholder="Enter your email"
454
- />
455
- </div>
456
- <div className="space-y-2">
457
- <Label htmlFor="category">Category</Label>
458
- <Select
459
- value={formData.category}
460
- onValueChange={(value) =>
461
- setFormData({ ...formData, category: value })
462
- }
463
- >
464
- <SelectTrigger>
465
- <SelectValue placeholder="Select a category" />
466
- </SelectTrigger>
467
- <SelectContent>
468
- <SelectItem value="general">General Inquiry</SelectItem>
469
- <SelectItem value="support">Technical Support</SelectItem>
470
- <SelectItem value="sales">Sales Question</SelectItem>
471
- <SelectItem value="feedback">Feedback</SelectItem>
472
- </SelectContent>
473
- </Select>
474
- </div>
475
- <div className="space-y-2">
476
- <Label htmlFor="priority">Priority</Label>
477
- <Select
478
- value={formData.priority}
479
- onValueChange={(value) =>
480
- setFormData({ ...formData, priority: value })
481
- }
482
- >
483
- <SelectTrigger>
484
- <SelectValue placeholder="Select priority level" />
485
- </SelectTrigger>
486
- <SelectContent>
487
- <SelectItem value="low">Low</SelectItem>
488
- <SelectItem value="medium">Medium</SelectItem>
489
- <SelectItem value="high">High</SelectItem>
490
- <SelectItem value="urgent">Urgent</SelectItem>
491
- </SelectContent>
492
- </Select>
493
- </div>
494
- <div className="space-y-2">
495
- <Label htmlFor="message">Message</Label>
496
- <Textarea
497
- id="message"
498
- value={formData.message}
499
- onChange={(e) =>
500
- setFormData({ ...formData, message: e.target.value })
501
- }
502
- placeholder="Enter your message"
503
- rows={4}
504
- />
505
- </div>
506
- <div className="flex items-center space-x-2">
507
- <Checkbox
508
- id="newsletter"
509
- checked={formData.newsletter}
510
- onCheckedChange={(checked) =>
511
- setFormData({ ...formData, newsletter: !!checked })
512
- }
513
- />
514
- <Label htmlFor="newsletter" className="text-sm">
515
- Subscribe to newsletter
516
- </Label>
517
- </div>
518
- </form>
519
- <DrawerFooter>
520
- <Button
521
- disabled={!formData.name || !formData.email || !formData.message}
522
- onClick={handleSubmit}
523
- >
524
- Submit
525
- </Button>
526
- <DrawerClose asChild>
527
- <Button variant="outline">Cancel</Button>
528
- </DrawerClose>
529
- </DrawerFooter>
530
- </DrawerContent>
531
- </Drawer>
532
- )
533
- },
534
- parameters: {
535
- docs: {
536
- description: {
537
- story:
538
- "Form drawer with select components instead of native select tags, demonstrating proper form handling and validation.",
539
- },
540
- },
541
- },
542
- }
396
+ <div className="border-fm-divider-secondary border-t pt-4" />
543
397
 
544
- // 3. Settings Drawer with Select Components
545
- export const SettingsDrawer: Story = {
546
- render: () => {
547
- const [settings, setSettings] = useState({
548
- theme: "dark",
549
- notifications: "important",
550
- language: "en",
551
- timezone: "utc",
552
- })
398
+ <div className="space-y-2">
399
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
400
+ Variant
401
+ </p>
402
+ <div className="flex flex-wrap gap-1">
403
+ {variants.map((v) => (
404
+ <button
405
+ key={v}
406
+ onClick={() => setVariant(v)}
407
+ className={btnCls(variant === v)}
408
+ >
409
+ {v}
410
+ </button>
411
+ ))}
412
+ </div>
413
+ </div>
553
414
 
554
- return (
555
- <Drawer>
556
- <DrawerTrigger asChild>
557
- <Button>Open Settings</Button>
558
- </DrawerTrigger>
559
- <DrawerContent>
560
- <DrawerHeader>
561
- <DrawerTitle>Settings</DrawerTitle>
562
- <DrawerDescription>
563
- Configure your application preferences.
564
- </DrawerDescription>
565
- </DrawerHeader>
566
- <div className="space-y-6 overflow-auto p-4">
567
- <div className="space-y-4">
568
- <h3 className="text-sm font-medium">Appearance</h3>
569
- <div className="space-y-2">
570
- <Label htmlFor="theme">Theme</Label>
571
- <Select
572
- value={settings.theme}
573
- onValueChange={(value) =>
574
- setSettings({ ...settings, theme: value })
575
- }
576
- >
577
- <SelectTrigger>
578
- <SelectValue />
579
- </SelectTrigger>
580
- <SelectContent>
581
- <SelectItem value="light">Light</SelectItem>
582
- <SelectItem value="dark">Dark</SelectItem>
583
- <SelectItem value="system">System</SelectItem>
584
- </SelectContent>
585
- </Select>
586
- </div>
587
- </div>
588
- <div className="space-y-4">
589
- <h3 className="text-sm font-medium">Notifications</h3>
590
- <div className="space-y-2">
591
- <Label htmlFor="notifications">Email Notifications</Label>
592
- <Select
593
- value={settings.notifications}
594
- onValueChange={(value) =>
595
- setSettings({ ...settings, notifications: value })
596
- }
597
- >
598
- <SelectTrigger>
599
- <SelectValue />
600
- </SelectTrigger>
601
- <SelectContent>
602
- <SelectItem value="all">All notifications</SelectItem>
603
- <SelectItem value="important">Important only</SelectItem>
604
- <SelectItem value="none">None</SelectItem>
605
- </SelectContent>
606
- </Select>
607
- </div>
608
- </div>
609
- <div className="space-y-4">
610
- <h3 className="text-sm font-medium">Regional</h3>
611
- <div className="space-y-2">
612
- <Label htmlFor="language">Language</Label>
613
- <Select
614
- value={settings.language}
615
- onValueChange={(value) =>
616
- setSettings({ ...settings, language: value })
617
- }
618
- >
619
- <SelectTrigger>
620
- <SelectValue />
621
- </SelectTrigger>
622
- <SelectContent>
623
- <SelectItem value="en">English</SelectItem>
624
- <SelectItem value="es">Spanish</SelectItem>
625
- <SelectItem value="fr">French</SelectItem>
626
- <SelectItem value="de">German</SelectItem>
627
- </SelectContent>
628
- </Select>
629
- </div>
630
- <div className="space-y-2">
631
- <Label htmlFor="timezone">Timezone</Label>
632
- <Select
633
- value={settings.timezone}
634
- onValueChange={(value) =>
635
- setSettings({ ...settings, timezone: value })
636
- }
637
- >
638
- <SelectTrigger>
639
- <SelectValue />
640
- </SelectTrigger>
641
- <SelectContent>
642
- <SelectItem value="utc">UTC</SelectItem>
643
- <SelectItem value="est">Eastern Time</SelectItem>
644
- <SelectItem value="pst">Pacific Time</SelectItem>
645
- <SelectItem value="gmt">GMT</SelectItem>
646
- </SelectContent>
647
- </Select>
648
- </div>
649
- </div>
650
- </div>
651
- <DrawerFooter>
652
- <Button onClick={() => console.log("Settings saved:", settings)}>
653
- Save Settings
654
- </Button>
655
- <DrawerClose asChild>
656
- <Button variant="outline">Cancel</Button>
657
- </DrawerClose>
658
- </DrawerFooter>
659
- </DrawerContent>
660
- </Drawer>
661
- )
662
- },
663
- parameters: {
664
- docs: {
665
- description: {
666
- story:
667
- "Settings drawer showcasing select components for configuration options with proper state management.",
668
- },
669
- },
670
- },
671
- }
415
+ <div className="border-fm-divider-secondary border-t pt-4" />
672
416
 
673
- // 4. Nested Drawers
674
- export const NestedDrawers: Story = {
675
- render: () => {
676
- const [isNestedOpen, setIsNestedOpen] = useState(false)
417
+ <div className="space-y-2">
418
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
419
+ Opacity
420
+ </p>
421
+ <div className="flex flex-wrap gap-1">
422
+ {levels.map((l) => (
423
+ <button
424
+ key={l}
425
+ onClick={() => setOpacity(l)}
426
+ className={btnCls(opacity === l)}
427
+ >
428
+ {l}
429
+ </button>
430
+ ))}
431
+ </div>
432
+ </div>
677
433
 
678
- return (
679
- <Drawer>
680
- <DrawerTrigger asChild>
681
- <Button>Open Parent Drawer</Button>
682
- </DrawerTrigger>
683
- <DrawerContent>
684
- <DrawerHeader>
685
- <DrawerTitle>Parent Drawer</DrawerTitle>
686
- <DrawerDescription>
687
- This drawer contains a nested drawer example.
688
- </DrawerDescription>
689
- </DrawerHeader>
690
- <div className="space-y-4 p-4">
691
- <p className="text-muted-foreground text-sm">
692
- This is the parent drawer content.
693
- </p>
694
- <Drawer open={isNestedOpen} onOpenChange={setIsNestedOpen}>
695
- <DrawerTrigger asChild>
696
- <Button variant="outline">Open Nested Drawer</Button>
697
- </DrawerTrigger>
698
- <DrawerContent>
699
- <DrawerHeader>
700
- <DrawerTitle>Nested Drawer</DrawerTitle>
701
- <DrawerDescription>
702
- This is a nested drawer within the parent drawer.
703
- </DrawerDescription>
704
- </DrawerHeader>
705
- <div className="p-4">
706
- <p className="text-muted-foreground text-sm">
707
- Nested drawer content goes here.
434
+ <div className="space-y-2">
435
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
436
+ Glass
708
437
  </p>
438
+ <div className="flex flex-wrap gap-1">
439
+ {levels.map((l) => (
440
+ <button
441
+ key={l}
442
+ onClick={() => setGlass(l)}
443
+ className={btnCls(glass === l)}
444
+ >
445
+ {l}
446
+ </button>
447
+ ))}
448
+ </div>
709
449
  </div>
710
- <DrawerFooter>
711
- <Button onClick={() => setIsNestedOpen(false)}>
712
- Close Nested
713
- </Button>
714
- <DrawerClose asChild>
715
- <Button variant="outline">Cancel</Button>
716
- </DrawerClose>
717
- </DrawerFooter>
718
- </DrawerContent>
719
- </Drawer>
720
- </div>
721
- <DrawerFooter>
722
- <Button>Save</Button>
723
- <DrawerClose asChild>
724
- <Button variant="outline">Close Parent</Button>
725
- </DrawerClose>
726
- </DrawerFooter>
727
- </DrawerContent>
728
- </Drawer>
729
- )
730
- },
731
- parameters: {
732
- docs: {
733
- description: {
734
- story:
735
- "Nested drawer example demonstrating proper modal stacking and z-index management.",
736
- },
737
- },
738
- },
739
- }
740
450
 
741
- // 5. Custom Close Button
742
- export const CustomCloseButton: Story = {
743
- render: () => (
744
- <Drawer>
745
- <DrawerTrigger asChild>
746
- <Button>Open Drawer with Custom Close</Button>
747
- </DrawerTrigger>
748
- <DrawerContent>
749
- <DrawerHeader>
750
- <div className="flex items-center justify-between">
751
- <div className="flex-1 text-center">
752
- <DrawerTitle>Custom Close Button</DrawerTitle>
753
- <DrawerDescription>
754
- This drawer has a custom close button in the header.
755
- </DrawerDescription>
451
+ <div className="space-y-2">
452
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
453
+ Noise
454
+ </p>
455
+ <div className="flex flex-wrap gap-1">
456
+ {levels.map((l) => (
457
+ <button
458
+ key={l}
459
+ onClick={() => setNoise(l)}
460
+ className={btnCls(noise === l)}
461
+ >
462
+ {l}
463
+ </button>
464
+ ))}
465
+ </div>
466
+ </div>
467
+
468
+ <div className="border-fm-divider-secondary border-t pt-4" />
469
+
470
+ <div className="flex items-center gap-2">
471
+ <Checkbox
472
+ id="swipe-btn"
473
+ checked={showSwipeButton}
474
+ onCheckedChange={(c) => setShowSwipeButton(!!c)}
475
+ />
476
+ <Label
477
+ htmlFor="swipe-btn"
478
+ className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm"
479
+ >
480
+ Swipe handle
481
+ </Label>
482
+ </div>
483
+ </div>
484
+
485
+ {/* Preview stage */}
486
+ <div className="flex flex-col gap-3 lg:col-span-2">
487
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary flex min-h-48 flex-col items-center justify-center gap-4 rounded-xl border p-8">
488
+ {submitted && (
489
+ <div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border px-4 py-2">
490
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
491
+ Form submitted for{" "}
492
+ <span className="text-fm-primary font-medium">
493
+ {name}
494
+ </span>
495
+ </p>
496
+ </div>
497
+ )}
498
+
499
+ <Drawer direction={direction}>
500
+ <DrawerTrigger asChild>
501
+ <Button onClick={() => setSubmitted(false)}>
502
+ Open Drawer
503
+ </Button>
504
+ </DrawerTrigger>
505
+ <DrawerContent
506
+ variant={variant}
507
+ opacity={opacity}
508
+ glass={glass}
509
+ noise={noise}
510
+ showSwipeButton={showSwipeButton}
511
+ >
512
+ <DrawerHeader>
513
+ <DrawerTitle>Quick Contact</DrawerTitle>
514
+ <DrawerDescription>
515
+ Fill out the form to send a message.
516
+ </DrawerDescription>
517
+ </DrawerHeader>
518
+
519
+ <div className="space-y-4 p-4">
520
+ <div className="space-y-2">
521
+ <Label htmlFor="drawer-name">Name</Label>
522
+ <Input
523
+ id="drawer-name"
524
+ placeholder="Your name"
525
+ value={name}
526
+ onChange={(e) => setName(e.target.value)}
527
+ />
528
+ </div>
529
+ <div className="space-y-2">
530
+ <Label htmlFor="drawer-email">Email</Label>
531
+ <Input
532
+ id="drawer-email"
533
+ type="email"
534
+ placeholder="your@email.com"
535
+ value={email}
536
+ onChange={(e) => setEmail(e.target.value)}
537
+ />
538
+ </div>
539
+ </div>
540
+
541
+ <DrawerFooter>
542
+ <DrawerClose asChild>
543
+ <Button
544
+ disabled={!name || !email}
545
+ onClick={() => setSubmitted(true)}
546
+ >
547
+ Submit
548
+ </Button>
549
+ </DrawerClose>
550
+ <DrawerClose asChild>
551
+ <Button variant="outline">Cancel</Button>
552
+ </DrawerClose>
553
+ </DrawerFooter>
554
+ </DrawerContent>
555
+ </Drawer>
556
+ </div>
557
+
558
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
559
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
560
+ {`<Drawer direction="${direction}"><DrawerContent variant="${variant}" opacity="${opacity}" glass="${glass}" noise="${noise}" showSwipeButton={${showSwipeButton}} />`}
561
+ </code>
562
+ </div>
563
+ </div>
756
564
  </div>
757
- <DrawerClose asChild>
758
- <Button variant="text" size="sm" className="ml-4">
759
- <CrossIcon className="h-4 w-4" />
760
- </Button>
761
- </DrawerClose>
762
565
  </div>
763
- </DrawerHeader>
566
+ </div>
567
+ )
568
+ }
764
569
 
765
- <DrawerFooter>
766
- <Button>Confirm</Button>
767
- <DrawerClose asChild>
768
- <Button variant="outline">Cancel</Button>
769
- </DrawerClose>
770
- </DrawerFooter>
771
- </DrawerContent>
772
- </Drawer>
773
- ),
570
+ return <InteractiveDemo />
571
+ },
774
572
  parameters: {
775
573
  docs: {
776
574
  description: {
777
575
  story:
778
- "Drawer with custom close button positioned in the header for enhanced user experience.",
576
+ "Live configurator select direction, variant, overlay settings, and swipe handle, then open the drawer and submit the form inside to see state feedback.",
779
577
  },
780
578
  },
781
579
  },
782
580
  }
783
581
 
784
- // 6. Accessibility Example
785
- export const AccessibilityExample: Story = {
786
- render: () => {
787
- return (
788
- <Drawer>
789
- <DrawerTrigger asChild>
790
- <Button>Accessible Drawer Demo</Button>
791
- </DrawerTrigger>
792
- <DrawerContent>
793
- <DrawerHeader>
794
- <DrawerTitle>Accessibility Features</DrawerTitle>
795
- <DrawerDescription>
796
- This drawer demonstrates proper accessibility implementation.
797
- </DrawerDescription>
798
- </DrawerHeader>
582
+ // ─── UseCases ─────────────────────────────────────────────────────────────────
799
583
 
800
- <div className="space-y-4 overflow-auto p-4">
801
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
802
- <h4 className="text-fm-primary mb-2 font-medium">
803
- Keyboard Navigation
804
- </h4>
805
- <ul className="text-fm-primary/80 space-y-1 text-sm">
806
- <li>
807
- •{" "}
808
- <kbd className="bg-fm-surface-secondary rounded px-1">
809
- Tab
810
- </kbd>{" "}
811
- - Navigate between elements
812
- </li>
813
- <li>
814
- •{" "}
815
- <kbd className="bg-fm-surface-secondary rounded px-1">
816
- Escape
817
- </kbd>{" "}
818
- - Close drawer
819
- </li>
820
- <li>
821
- •{" "}
822
- <kbd className="bg-fm-surface-secondary rounded px-1">
823
- Enter
824
- </kbd>{" "}
825
- - Activate buttons
826
- </li>
827
- <li>
828
- •{" "}
829
- <kbd className="bg-fm-surface-secondary rounded px-1">
830
- Space
831
- </kbd>{" "}
832
- - Activate buttons
833
- </li>
834
- </ul>
835
- </div>
584
+ export const UseCases: Story = {
585
+ render: () => {
586
+ // Track actions bottom drawer
587
+ const TrackActionsDrawer = () => {
588
+ const [liked, setLiked] = useState(false)
589
+ const [queued, setQueued] = useState(false)
836
590
 
837
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
838
- <h4 className="text-fm-primary mb-2 font-medium">
839
- Focus Management
840
- </h4>
841
- <ul className="text-fm-primary/80 space-y-1 text-sm">
842
- <li>• Automatic focus trapping within drawer</li>
843
- <li>• Focus restoration when drawer closes</li>
844
- <li>• Proper focus order for all interactive elements</li>
845
- <li>• Screen reader announcements for state changes</li>
846
- </ul>
847
- </div>
591
+ return (
592
+ <Drawer direction="bottom">
593
+ <DrawerTrigger asChild>
594
+ <Button variant="outline" size="sm">
595
+ Track actions
596
+ </Button>
597
+ </DrawerTrigger>
598
+ <DrawerContent showSwipeButton>
599
+ <DrawerHeader>
600
+ <DrawerTitle>Midnight Drive</DrawerTitle>
601
+ <DrawerDescription>Lo-fi Chill · 3:42</DrawerDescription>
602
+ </DrawerHeader>
848
603
 
849
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
850
- <h4 className="text-fm-primary mb-2 font-medium">Drag Support</h4>
851
- <ul className="text-fm-primary/80 space-y-1 text-sm">
852
- <li>• Drag to close functionality</li>
853
- <li>• Smooth animations during drag</li>
854
- <li>• Haptic feedback on mobile devices</li>
855
- <li>• Proper gesture recognition</li>
856
- </ul>
604
+ <div className="space-y-1 p-4">
605
+ {[
606
+ {
607
+ label: liked ? "Remove from Liked" : "Like this track",
608
+ icon: TickCircleIcon,
609
+ action: () => setLiked((v) => !v),
610
+ active: liked,
611
+ },
612
+ {
613
+ label: queued ? "Remove from queue" : "Add to queue",
614
+ icon: MusicalNoteIcon,
615
+ action: () => setQueued((v) => !v),
616
+ active: queued,
617
+ },
618
+ {
619
+ label: "Go to artist",
620
+ icon: ChevronRightIcon,
621
+ action: () => {},
622
+ active: false,
623
+ },
624
+ {
625
+ label: "Share",
626
+ icon: SearchIcon,
627
+ action: () => {},
628
+ active: false,
629
+ },
630
+ ].map((item) => (
631
+ <button
632
+ key={item.label}
633
+ onClick={item.action}
634
+ className={`flex w-full items-center gap-3 rounded-lg px-3 py-3 text-left transition-colors ${
635
+ item.active
636
+ ? "bg-fm-surface-positive-sec text-fm-primary"
637
+ : "text-fm-primary hover:bg-fm-surface-secondary"
638
+ }`}
639
+ >
640
+ <item.icon className="text-fm-secondary h-5 w-5 shrink-0" />
641
+ <span className="font-fm-text text-fm-md leading-fm-md">
642
+ {item.label}
643
+ </span>
644
+ </button>
645
+ ))}
857
646
  </div>
858
- </div>
859
647
 
860
- <DrawerFooter>
861
- <DrawerClose asChild>
862
- <Button>Close Drawer</Button>
863
- </DrawerClose>
864
- </DrawerFooter>
865
- </DrawerContent>
866
- </Drawer>
867
- )
868
- },
869
- parameters: {
870
- docs: {
871
- description: {
872
- story:
873
- "Comprehensive accessibility example showcasing keyboard navigation, focus management, and drag support features.",
874
- },
875
- },
876
- },
877
- }
648
+ <DrawerFooter>
649
+ <DrawerClose asChild>
650
+ <Button variant="outline">Close</Button>
651
+ </DrawerClose>
652
+ </DrawerFooter>
653
+ </DrawerContent>
654
+ </Drawer>
655
+ )
656
+ }
878
657
 
879
- // 7. Drawer without Overlay
880
- export const DrawerWithoutOverlay: Story = {
881
- render: () => (
882
- <div>
883
- <Drawer>
884
- <DrawerTrigger asChild>
885
- <Button className="relative z-10">Open Drawer (No Overlay)</Button>
886
- </DrawerTrigger>
887
- <DrawerContent showOverlay={false}>
888
- <DrawerHeader>
889
- <DrawerTitle>Drawer Without Overlay</DrawerTitle>
890
- <DrawerDescription>
891
- This drawer opens without a backdrop overlay, allowing background
892
- content to remain visible.
893
- </DrawerDescription>
894
- </DrawerHeader>
895
- <DrawerFooter>
896
- <Button>Apply Changes</Button>
897
- <DrawerClose asChild>
898
- <Button variant="outline">Cancel</Button>
899
- </DrawerClose>
900
- </DrawerFooter>
901
- </DrawerContent>
902
- </Drawer>
903
- </div>
904
- ),
905
- parameters: {
906
- docs: {
907
- description: {
908
- story:
909
- "Drawer example with `showOverlay={false}` demonstrating how to create non-modal drawer interactions that don't obscure background content.",
910
- },
911
- },
912
- },
913
- }
658
+ // Side navigation drawer
659
+ const NavDrawer = () => {
660
+ const [active, setActive] = useState("Home")
661
+ const items = [
662
+ { label: "Home", icon: SiteLogoIcon },
663
+ { label: "Search", icon: SearchIcon },
664
+ { label: "Library", icon: MusicalNoteIcon },
665
+ { label: "Settings", icon: MaintenanceIcon },
666
+ ]
914
667
 
915
- // 8. Overlay Variations
916
- export const OverlayVariations: Story = {
917
- render: () => {
918
- const OverlayDrawer = ({
919
- opacity,
920
- glass,
921
- noise,
922
- title,
923
- description,
924
- }: any) => {
925
668
  return (
926
- <Drawer>
669
+ <Drawer direction="left">
927
670
  <DrawerTrigger asChild>
928
671
  <Button variant="outline" size="sm">
929
- {title}
672
+ Side navigation
930
673
  </Button>
931
674
  </DrawerTrigger>
932
- <DrawerContent
933
- opacity={opacity}
934
- glass={glass}
935
- noise={noise}
936
- variant="neutral"
937
- >
675
+ <DrawerContent>
938
676
  <DrawerHeader>
939
- <DrawerTitle>{title}</DrawerTitle>
940
- <DrawerDescription>{description}</DrawerDescription>
677
+ <DrawerTitle>Navigation</DrawerTitle>
678
+ <DrawerDescription>Main app navigation</DrawerDescription>
941
679
  </DrawerHeader>
942
- <div className="py-4">
943
- <div className="text-fm-primary/60 grid grid-cols-2 gap-2 text-xs">
944
- <div>
945
- Opacity:{" "}
946
- <span className="text-fm-primary">
947
- {opacity || "default"}
680
+
681
+ <nav className="space-y-1 p-4">
682
+ {items.map((item) => (
683
+ <button
684
+ key={item.label}
685
+ onClick={() => setActive(item.label)}
686
+ className={`flex w-full items-center gap-3 rounded-lg px-3 py-3 text-left transition-colors ${
687
+ active === item.label
688
+ ? "bg-fm-surface-info-sec text-fm-primary"
689
+ : "text-fm-primary hover:bg-fm-surface-secondary"
690
+ }`}
691
+ >
692
+ <item.icon className="text-fm-secondary h-5 w-5 shrink-0" />
693
+ <span className="font-fm-text text-fm-md leading-fm-md">
694
+ {item.label}
948
695
  </span>
696
+ </button>
697
+ ))}
698
+ </nav>
699
+
700
+ <DrawerFooter>
701
+ <DrawerClose asChild>
702
+ <Button variant="outline">Close</Button>
703
+ </DrawerClose>
704
+ </DrawerFooter>
705
+ </DrawerContent>
706
+ </Drawer>
707
+ )
708
+ }
709
+
710
+ // Settings panel drawer
711
+ const SettingsDrawer = () => {
712
+ const [autoplay, setAutoplay] = useState(true)
713
+ const [notifications, setNotifications] = useState(false)
714
+ const [hq, setHq] = useState(true)
715
+
716
+ return (
717
+ <Drawer direction="right">
718
+ <DrawerTrigger asChild>
719
+ <Button variant="outline" size="sm">
720
+ Settings panel
721
+ </Button>
722
+ </DrawerTrigger>
723
+ <DrawerContent>
724
+ <DrawerHeader>
725
+ <DrawerTitle>Playback Settings</DrawerTitle>
726
+ <DrawerDescription>
727
+ Configure your listening experience
728
+ </DrawerDescription>
729
+ </DrawerHeader>
730
+
731
+ <div className="space-y-5 p-4">
732
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
733
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold tracking-widest uppercase">
734
+ Playback
735
+ </p>
736
+ <div className="space-y-3">
737
+ {[
738
+ { label: "Autoplay", value: autoplay, set: setAutoplay },
739
+ { label: "High quality audio", value: hq, set: setHq },
740
+ ].map((s) => (
741
+ <div
742
+ key={s.label}
743
+ className="flex items-center justify-between"
744
+ >
745
+ <span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
746
+ {s.label}
747
+ </span>
748
+ <Checkbox
749
+ checked={s.value}
750
+ onCheckedChange={(c) => s.set(!!c)}
751
+ />
752
+ </div>
753
+ ))}
949
754
  </div>
950
- <div>
951
- Glass:{" "}
952
- <span className="text-fm-primary">{glass || "default"}</span>
953
- </div>
954
- <div>
955
- Noise:{" "}
956
- <span className="text-fm-primary">{noise || "none"}</span>
957
- </div>
958
- <div>
959
- Variant: <span className="text-fm-primary">neutral</span>
755
+ </div>
756
+
757
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
758
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold tracking-widest uppercase">
759
+ Notifications
760
+ </p>
761
+ <div className="flex items-center justify-between">
762
+ <span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
763
+ Push notifications
764
+ </span>
765
+ <Checkbox
766
+ checked={notifications}
767
+ onCheckedChange={(c) => setNotifications(!!c)}
768
+ />
960
769
  </div>
961
770
  </div>
962
771
  </div>
772
+
963
773
  <DrawerFooter>
964
774
  <DrawerClose asChild>
965
- <Button>Close</Button>
775
+ <Button>Save</Button>
776
+ </DrawerClose>
777
+ <DrawerClose asChild>
778
+ <Button variant="outline">Cancel</Button>
966
779
  </DrawerClose>
967
780
  </DrawerFooter>
968
781
  </DrawerContent>
@@ -971,180 +784,39 @@ export const OverlayVariations: Story = {
971
784
  }
972
785
 
973
786
  return (
974
- <div className="space-y-8">
975
- <div className="text-center">
976
- <h3 className="text-fm-primary mb-2 font-medium">
977
- Overlay Variations
978
- </h3>
979
- <p className="text-fm-primary/60 text-sm">
980
- Different overlay effects for various visual styles
787
+ <div className="mx-auto max-w-3xl space-y-8 p-8">
788
+ <div className="space-y-3">
789
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
790
+ Mobile Bottom Drawer — Track Actions
791
+ </h4>
792
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
793
+ A bottom sheet presenting contextual actions for the currently
794
+ playing track. Includes a swipe handle and stateful like/queue
795
+ toggles.
981
796
  </p>
797
+ <TrackActionsDrawer />
982
798
  </div>
983
799
 
984
- <div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
985
- <OverlayDrawer
986
- opacity="low"
987
- title="Low Opacity"
988
- description="Subtle background dimming (40%)"
989
- />
990
- <OverlayDrawer
991
- opacity="medium"
992
- title="Medium Opacity"
993
- description="Balanced background dimming (60%)"
994
- />
995
- <OverlayDrawer
996
- opacity="high"
997
- title="High Opacity"
998
- description="Strong background dimming (80%)"
999
- />
1000
- <OverlayDrawer
1001
- opacity="none"
1002
- title="Full Opacity"
1003
- description="Complete background coverage (100%)"
1004
- />
1005
- <OverlayDrawer
1006
- glass="low"
1007
- title="Low Glass"
1008
- description="Subtle backdrop blur effect"
1009
- />
1010
- <OverlayDrawer
1011
- glass="medium"
1012
- title="Medium Glass"
1013
- description="Balanced backdrop blur effect"
1014
- />
1015
- <OverlayDrawer
1016
- glass="high"
1017
- title="High Glass"
1018
- description="Strong backdrop blur effect"
1019
- />
1020
- <OverlayDrawer
1021
- noise="low"
1022
- title="Low Noise"
1023
- description="Subtle texture pattern"
1024
- />
1025
- <OverlayDrawer
1026
- noise="medium"
1027
- title="Medium Noise"
1028
- description="Balanced texture pattern"
1029
- />
1030
- <OverlayDrawer
1031
- noise="high"
1032
- title="High Noise"
1033
- description="Strong texture pattern"
1034
- />
1035
- <OverlayDrawer
1036
- opacity="medium"
1037
- glass="medium"
1038
- noise="medium"
1039
- title="Balanced"
1040
- description="All effects at medium level"
1041
- />
1042
- </div>
1043
- </div>
1044
- )
1045
- },
1046
- parameters: {
1047
- docs: {
1048
- description: {
1049
- story:
1050
- "Showcase of different overlay configurations demonstrating various opacity, glass, and noise effects.",
1051
- },
1052
- },
1053
- },
1054
- }
1055
-
1056
- // 9. Variant Examples
1057
- export const VariantExamples: Story = {
1058
- render: () => {
1059
- return (
1060
- <div className="space-y-8">
1061
- <div className="text-center">
1062
- <h3 className="text-fm-primary mb-2 font-medium">Drawer Variants</h3>
1063
- <p className="text-fm-primary/60 text-sm">
1064
- Compare the neutral (default) and gradient variants
800
+ <div className="space-y-3">
801
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
802
+ Side Navigation Drawer
803
+ </h4>
804
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
805
+ A left-side navigation drawer for switching between primary app
806
+ sections. Active item is highlighted.
1065
807
  </p>
808
+ <NavDrawer />
1066
809
  </div>
1067
810
 
1068
- <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
1069
- <div className="space-y-4">
1070
- <h4 className="text-fm-primary text-center font-medium">
1071
- Neutral Variant (Default)
1072
- </h4>
1073
- <Drawer>
1074
- <DrawerTrigger asChild>
1075
- <Button variant="outline" className="w-full">
1076
- Open Neutral Drawer
1077
- </Button>
1078
- </DrawerTrigger>
1079
- <DrawerContent variant="neutral">
1080
- <DrawerHeader>
1081
- <DrawerTitle>Neutral Variant</DrawerTitle>
1082
- <DrawerDescription>
1083
- This is the default neutral variant with frosted glass
1084
- background and border.
1085
- </DrawerDescription>
1086
- </DrawerHeader>
1087
- <div className="py-4">
1088
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
1089
- <h5 className="text-fm-primary mb-2 font-medium">
1090
- Features:
1091
- </h5>
1092
- <ul className="text-fm-primary/70 space-y-1 text-sm">
1093
- <li>• Frosted glass background</li>
1094
- <li>• Subtle border</li>
1095
- <li>• Backdrop blur effect</li>
1096
- <li>• Semi-transparent appearance</li>
1097
- </ul>
1098
- </div>
1099
- </div>
1100
- <DrawerFooter>
1101
- <DrawerClose asChild>
1102
- <Button>Close</Button>
1103
- </DrawerClose>
1104
- </DrawerFooter>
1105
- </DrawerContent>
1106
- </Drawer>
1107
- </div>
1108
-
1109
- <div className="space-y-4">
1110
- <h4 className="text-fm-primary text-center font-medium">
1111
- Gradient Variant
1112
- </h4>
1113
- <Drawer>
1114
- <DrawerTrigger asChild>
1115
- <Button variant="outline" className="w-full">
1116
- Open Gradient Drawer
1117
- </Button>
1118
- </DrawerTrigger>
1119
- <DrawerContent variant="gradient">
1120
- <DrawerHeader>
1121
- <DrawerTitle>Gradient Variant</DrawerTitle>
1122
- <DrawerDescription>
1123
- This is the gradient variant with white gradient background
1124
- and no border.
1125
- </DrawerDescription>
1126
- </DrawerHeader>
1127
- <div className="py-4">
1128
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
1129
- <h5 className="text-fm-primary mb-2 font-medium">
1130
- Features:
1131
- </h5>
1132
- <ul className="text-fm-primary/70 space-y-1 text-sm">
1133
- <li>• White gradient background</li>
1134
- <li>• No border</li>
1135
- <li>• Clean, modern appearance</li>
1136
- <li>• Solid background effect</li>
1137
- </ul>
1138
- </div>
1139
- </div>
1140
- <DrawerFooter>
1141
- <DrawerClose asChild>
1142
- <Button>Close</Button>
1143
- </DrawerClose>
1144
- </DrawerFooter>
1145
- </DrawerContent>
1146
- </Drawer>
1147
- </div>
811
+ <div className="space-y-3">
812
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
813
+ Settings Panel Drawer
814
+ </h4>
815
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
816
+ A right-side settings panel that groups playback and notification
817
+ preferences with interactive checkboxes.
818
+ </p>
819
+ <SettingsDrawer />
1148
820
  </div>
1149
821
  </div>
1150
822
  )
@@ -1153,43 +825,7 @@ export const VariantExamples: Story = {
1153
825
  docs: {
1154
826
  description: {
1155
827
  story:
1156
- "Simple comparison of the two drawer variants: neutral (default) with frosted glass background and gradient with white gradient background.",
1157
- },
1158
- },
1159
- },
1160
- }
1161
-
1162
- export const DrawerWithSwipeButton: Story = {
1163
- render: () => (
1164
- <div>
1165
- <Drawer>
1166
- <DrawerTrigger asChild>
1167
- <Button className="relative z-10">
1168
- Open Drawer (With Swipe button)
1169
- </Button>
1170
- </DrawerTrigger>
1171
- <DrawerContent showSwipeButton={true}>
1172
- <DrawerHeader>
1173
- <DrawerTitle>Drawer with Swipe button</DrawerTitle>
1174
- <DrawerDescription>
1175
- This drawer opens with a swipe button.
1176
- </DrawerDescription>
1177
- </DrawerHeader>
1178
- <DrawerFooter>
1179
- <Button>Apply Changes</Button>
1180
- <DrawerClose asChild>
1181
- <Button variant="outline">Cancel</Button>
1182
- </DrawerClose>
1183
- </DrawerFooter>
1184
- </DrawerContent>
1185
- </Drawer>
1186
- </div>
1187
- ),
1188
- parameters: {
1189
- docs: {
1190
- description: {
1191
- story:
1192
- "Drawer example with `showSwipeButton={true}` showing a swipe indicator button",
828
+ "Three realistic product scenarios: a mobile bottom track-actions sheet, a left-side app navigation drawer, and a right-side settings panel.",
1193
829
  },
1194
830
  },
1195
831
  },