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
@@ -1,24 +1,20 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import React, { useState } from "react"
3
- import { Badge } from "@components/badge"
4
3
  import { Button } from "@components/button"
5
4
  import { Checkbox } from "@components/checkbox"
6
- import { IconButton } from "@components/icon-button"
7
5
  import Input from "@components/input"
8
6
  import { Label } from "@components/label"
9
- import Textarea from "@components/textarea"
10
7
  import { AlertIcon } from "@icons/alert-icon"
11
- import { ArrowRightIcon } from "@icons/arrow-right-icon"
12
8
  import { ChevronRightIcon } from "@icons/chevron-right-icon"
13
- import { FeatureShineIcon } from "@icons/feature-shine-icon"
14
- import { FileChartIcon } from "@icons/file-chart-icon"
15
- import { MagicBookIcon } from "@icons/magic-book-icon"
16
9
  import { MaintenanceIcon } from "@icons/maintenance-icon"
10
+ import { MusicalNoteIcon } from "@icons/musical-note-icon"
17
11
  import { SearchIcon } from "@icons/search-icon"
18
12
  import { SiteLogoIcon } from "@icons/site-logo-icon"
19
13
  import { TickCircleIcon } from "@icons/tick-circle-icon"
20
14
  import type { Meta, StoryObj } from "@storybook/react-vite"
21
15
 
16
+ import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
17
+
22
18
  import {
23
19
  Sheet,
24
20
  SheetClose,
@@ -34,115 +30,30 @@ const meta: Meta<typeof Sheet> = {
34
30
  title: "Components/UI/Sheet",
35
31
  component: Sheet,
36
32
  parameters: {
37
- layout: "fullscreen",
38
- backgrounds: {
39
- default: "dark",
40
- values: [
41
- { name: "dark", value: "#0a0a0a" },
42
- { name: "light", value: "#ffffff" },
43
- ],
44
- },
33
+ layout: "centered",
45
34
  docs: {
46
35
  description: {
47
- component: `
48
- # Sheet Component
49
-
50
- A slide-out panel component built on Radix UI Dialog primitives that provides a drawer-like interface for displaying content from different sides of the screen.
51
-
52
- ## Features
53
-
54
- - **Multiple Sides**: Sheet can slide in from top, right, bottom, or left
55
- - **Variant Colors**: Neutral, positive, negative, warning, and info color variants
56
- - **Customizable Overlays**: Configurable opacity, glass effects, and noise textures
57
- - **Smooth Animations**: Slide animations with proper easing for each direction
58
- - **Accessible**: Full keyboard navigation and screen reader support
59
- - **Flexible Content**: Header, footer, and body sections with custom styling
60
- - **Auto Close Button**: Positioned close button with CrossIcon
61
- - **Portal Rendering**: Renders outside normal DOM hierarchy
62
- - **Focus Management**: Automatic focus trapping and restoration
63
- - **Border Accents**: Colored borders that match the variant
64
-
65
- ## Component Structure
66
-
67
- - **Sheet**: Root component that manages sheet state
68
- - **SheetTrigger**: Button or element that opens the sheet
69
- - **SheetContent**: Main sheet container with overlay, content, and close button
70
- - **SheetHeader**: Header section for title and description
71
- - **SheetFooter**: Footer section for action buttons
72
- - **SheetTitle**: Accessible title element
73
- - **SheetDescription**: Optional description text
74
- - **SheetClose**: Close button component
75
-
76
- ## Usage Examples
77
-
78
- ### Basic Sheet
79
- \`\`\`tsx
80
- <Sheet>
81
- <SheetTrigger asChild>
82
- <Button>Open Sheet</Button>
83
- </SheetTrigger>
84
- <SheetContent>
85
- <SheetHeader>
86
- <SheetTitle>Sheet Title</SheetTitle>
87
- <SheetDescription>Sheet description text.</SheetDescription>
88
- </SheetHeader>
89
- <div>Sheet content goes here.</div>
90
- <SheetFooter>
91
- <SheetClose asChild>
92
- <Button variant="outline">Cancel</Button>
93
- </SheetClose>
94
- <Button>Confirm</Button>
95
- </SheetFooter>
96
- </SheetContent>
97
- </Sheet>
98
- \`\`\`
99
-
100
- ### Sheet from Different Sides
101
- \`\`\`tsx
102
- <SheetContent side="left">
103
- {/* Left side sheet */}
104
- </SheetContent>
105
-
106
- <SheetContent side="right">
107
- {/* Right side sheet (default) */}
108
- </SheetContent>
109
-
110
- <SheetContent side="top">
111
- {/* Top side sheet */}
112
- </SheetContent>
113
-
114
- <SheetContent side="bottom">
115
- {/* Bottom side sheet */}
116
- </SheetContent>
117
- \`\`\`
118
-
119
- ### Colored Variants
120
- \`\`\`tsx
121
- <SheetContent variant="positive">
122
- {/* Success/positive themed sheet */}
123
- </SheetContent>
124
-
125
- <SheetContent variant="negative">
126
- {/* Error/negative themed sheet */}
127
- </SheetContent>
128
-
129
- <SheetContent variant="warning">
130
- {/* Warning themed sheet */}
131
- </SheetContent>
132
-
133
- <SheetContent variant="info">
134
- {/* Info themed sheet */}
135
- </SheetContent>
136
- \`\`\`
137
-
138
- ### Custom Overlay
139
- \`\`\`tsx
140
- <SheetContent opacity="high" glass="medium" noise="low">
141
- {/* High opacity overlay with glass effect and subtle noise */}
142
- </SheetContent>
143
- \`\`\`
144
- `,
36
+ component:
37
+ "A slide-out panel built on Radix UI Dialog primitives. Supports four entry sides, five semantic variants with matching gradient border accents, and configurable glass/noise overlays. Ideal for navigation drawers, detail panels, filter sidebars, and contextual action sheets.",
145
38
  },
39
+ page: () => (
40
+ <AuralComponentDocsPage
41
+ features={[
42
+ {
43
+ title: "4 Entry Sides",
44
+ description: "Top, bottom, left, right",
45
+ },
46
+ {
47
+ title: "5 Variant Borders",
48
+ description: "Neutral to negative",
49
+ },
50
+ {
51
+ title: "Glass & Noise",
52
+ description: "Overlay blur and grain",
53
+ },
54
+ ]}
55
+ />
56
+ ),
146
57
  },
147
58
  },
148
59
  tags: ["autodocs"],
@@ -151,914 +62,724 @@ A slide-out panel component built on Radix UI Dialog primitives that provides a
151
62
  export default meta
152
63
  type Story = StoryObj<typeof Sheet>
153
64
 
154
- // Demo background content
155
- const BackgroundContent = () => (
156
- <div className="min-h-screen bg-gradient-to-br from-blue-900 via-purple-900 to-pink-900 p-8">
157
- <div className="mx-auto max-w-4xl space-y-8">
158
- <header className="text-center">
159
- <h1 className="mb-4 text-4xl font-bold text-white">
160
- Main Content Area
161
- </h1>
162
- <p className="text-white/80">
163
- This is the main content that sits behind the sheet overlay
164
- </p>
165
- </header>
65
+ // ─── Configurations ────────────────────────────────────────────────────────────
166
66
 
167
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
168
- {Array.from({ length: 6 }, (_, i) => (
169
- <div
170
- key={i}
171
- className="rounded-lg border border-white/20 bg-white/10 p-6"
172
- >
173
- <h3 className="mb-2 text-lg font-semibold text-white">
174
- Content Block {i + 1}
175
- </h3>
176
- <p className="mb-4 text-sm text-white/70">
177
- Sample content that demonstrates the sheet overlay effect
178
- </p>
179
- <Button size="sm" variant="outline">
180
- Action
67
+ export const Configurations: Story = {
68
+ render: () => {
69
+ const SideSheet = ({ side, variant, label, description }: any) => (
70
+ <div className="space-y-2 text-center">
71
+ <Sheet>
72
+ <SheetTrigger asChild>
73
+ <Button variant="outline" size="sm">
74
+ {label}
181
75
  </Button>
182
- </div>
183
- ))}
76
+ </SheetTrigger>
77
+ <SheetContent side={side} variant={variant} container={null}>
78
+ <SheetHeader>
79
+ <SheetTitle>{label} Sheet</SheetTitle>
80
+ <SheetDescription>{description}</SheetDescription>
81
+ </SheetHeader>
82
+ <div className="py-4">
83
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
84
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
85
+ side="{side}" variant="{variant}"
86
+ </code>
87
+ </div>
88
+ </div>
89
+ <SheetFooter>
90
+ <SheetClose asChild>
91
+ <Button>Close</Button>
92
+ </SheetClose>
93
+ </SheetFooter>
94
+ </SheetContent>
95
+ </Sheet>
96
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
97
+ {label}
98
+ </p>
184
99
  </div>
185
- </div>
186
- </div>
187
- )
188
-
189
- // 1. Sheet Sides and Variants
190
- export const SidesAndVariants: Story = {
191
- render: () => (
192
- <div className="relative">
193
- <BackgroundContent />
194
-
195
- {/* Control Panel */}
196
- <div className="fixed top-4 left-1/2 z-50 -translate-x-1/2 transform">
197
- <div className="space-y-4 rounded-lg bg-black/80 p-6 backdrop-blur-sm">
198
- <h3 className="text-fm-primary text-center text-sm font-medium">
199
- Sheet Sides & Variants
200
- </h3>
201
-
202
- {/* Sides */}
203
- <div className="space-y-2">
204
- <h4 className="text-fm-secondary text-xs font-medium tracking-wide uppercase">
205
- Sides
206
- </h4>
207
- <div className="grid grid-cols-2 gap-2">
208
- {/* Left Sheet - Neutral */}
209
- <Sheet>
210
- <SheetTrigger asChild>
211
- <Button size="sm" variant="outline">
212
- Left
213
- </Button>
214
- </SheetTrigger>
215
- <SheetContent side="left" variant="neutral">
216
- <SheetHeader>
217
- <SheetTitle>Left Side Sheet</SheetTitle>
218
- <SheetDescription>
219
- Slides in from the left with neutral styling
220
- </SheetDescription>
221
- </SheetHeader>
222
- <div className="py-4">
223
- <div className="space-y-4">
224
- <div className="bg-fm-surface-secondary rounded-lg p-4">
225
- <h4 className="text-fm-primary mb-2 font-medium">
226
- Navigation Menu
227
- </h4>
228
- <div className="space-y-2">
229
- {["Dashboard", "Projects", "Team", "Settings"].map(
230
- (item) => (
231
- <div
232
- key={item}
233
- className="hover:bg-fm-surface-tertiary flex items-center gap-3 rounded p-2"
234
- >
235
- <SiteLogoIcon className="text-fm-secondary h-4 w-4" />
236
- <span className="text-fm-primary">{item}</span>
237
- </div>
238
- )
239
- )}
240
- </div>
241
- </div>
242
- </div>
243
- </div>
244
- </SheetContent>
245
- </Sheet>
100
+ )
246
101
 
247
- {/* Right Sheet - Positive */}
248
- <Sheet>
249
- <SheetTrigger asChild>
250
- <Button size="sm" variant="outline">
251
- Right
252
- </Button>
253
- </SheetTrigger>
254
- <SheetContent side="right" variant="positive">
255
- <SheetHeader>
256
- <SheetTitle>Right Side Sheet</SheetTitle>
257
- <SheetDescription>
258
- Slides in from the right with positive styling
259
- </SheetDescription>
260
- </SheetHeader>
261
- <div className="py-4">
262
- <div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-4">
263
- <div className="mb-2 flex items-center gap-2">
264
- <TickCircleIcon className="text-fm-icon-positive h-5 w-5" />
265
- <h4 className="text-fm-primary font-medium">
266
- Success Panel
267
- </h4>
268
- </div>
269
- <p className="text-fm-secondary text-sm">
270
- This demonstrates the positive variant with green accent
271
- border.
272
- </p>
273
- </div>
274
- </div>
275
- </SheetContent>
276
- </Sheet>
102
+ const OverlaySheet = ({ label, opacity, glass, noise }: any) => (
103
+ <div className="space-y-2 text-center">
104
+ <Sheet>
105
+ <SheetTrigger asChild>
106
+ <Button variant="outline" size="sm">
107
+ {label}
108
+ </Button>
109
+ </SheetTrigger>
110
+ <SheetContent
111
+ side="right"
112
+ variant="neutral"
113
+ opacity={opacity}
114
+ glass={glass}
115
+ noise={noise}
116
+ container={null}
117
+ >
118
+ <SheetHeader>
119
+ <SheetTitle>{label}</SheetTitle>
120
+ <SheetDescription>Overlay configuration demo.</SheetDescription>
121
+ </SheetHeader>
122
+ <div className="py-4">
123
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
124
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
125
+ {[
126
+ opacity && `opacity="${opacity}"`,
127
+ glass && `glass="${glass}"`,
128
+ noise && `noise="${noise}"`,
129
+ ]
130
+ .filter(Boolean)
131
+ .join(" ")}
132
+ </code>
133
+ </div>
134
+ </div>
135
+ <SheetFooter>
136
+ <SheetClose asChild>
137
+ <Button>Close</Button>
138
+ </SheetClose>
139
+ </SheetFooter>
140
+ </SheetContent>
141
+ </Sheet>
142
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
143
+ {label}
144
+ </p>
145
+ </div>
146
+ )
277
147
 
278
- {/* Top Sheet - Warning */}
279
- <Sheet>
280
- <SheetTrigger asChild>
281
- <Button size="sm" variant="outline">
282
- Top
283
- </Button>
284
- </SheetTrigger>
285
- <SheetContent side="top" variant="warning">
286
- <SheetHeader>
287
- <SheetTitle>Top Side Sheet</SheetTitle>
288
- <SheetDescription>
289
- Slides down from the top with warning styling
290
- </SheetDescription>
291
- </SheetHeader>
292
- <div className="py-4">
293
- <div className="border-fm-divider-warning bg-fm-surface-warning-sec rounded-lg border p-4">
294
- <div className="mb-2 flex items-center gap-2">
295
- <AlertIcon className="text-fm-warning h-5 w-5" />
296
- <h4 className="text-fm-primary font-medium">
297
- Warning Notice
298
- </h4>
299
- </div>
300
- <p className="text-fm-secondary text-sm">
301
- Top sheets are great for notifications and warnings.
302
- </p>
303
- </div>
304
- </div>
305
- </SheetContent>
306
- </Sheet>
148
+ return (
149
+ <div className="space-y-8">
150
+ {/* All four sides */}
151
+ <div className="space-y-3">
152
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
153
+ All Four Sides
154
+ </h4>
155
+ <div className="flex flex-wrap gap-6">
156
+ <SideSheet
157
+ side="left"
158
+ variant="neutral"
159
+ label="Left"
160
+ description="Slides in from the left — navigation and filter panels."
161
+ />
162
+ <SideSheet
163
+ side="right"
164
+ variant="neutral"
165
+ label="Right"
166
+ description="Slides in from the right — detail and settings panels."
167
+ />
168
+ <SideSheet
169
+ side="top"
170
+ variant="neutral"
171
+ label="Top"
172
+ description="Slides down from the top — notifications and alerts."
173
+ />
174
+ <SideSheet
175
+ side="bottom"
176
+ variant="neutral"
177
+ label="Bottom"
178
+ description="Slides up from the bottom — mobile-style action sheets."
179
+ />
180
+ </div>
181
+ </div>
307
182
 
308
- {/* Bottom Sheet - Info */}
309
- <Sheet>
310
- <SheetTrigger asChild>
311
- <Button size="sm" variant="outline">
312
- Bottom
313
- </Button>
314
- </SheetTrigger>
315
- <SheetContent side="bottom" variant="info">
316
- <SheetHeader>
317
- <SheetTitle>Bottom Side Sheet</SheetTitle>
318
- <SheetDescription>
319
- Slides up from the bottom with info styling
320
- </SheetDescription>
321
- </SheetHeader>
322
- <div className="py-4">
323
- <div className="border-fm-divider-secondary bg-fm-surface-info-sec rounded-lg border p-4">
324
- <div className="mb-2 flex items-center gap-2">
325
- <FileChartIcon className="text-fm-icon-info h-5 w-5" />
326
- <h4 className="text-fm-primary font-medium">
327
- Information Panel
328
- </h4>
329
- </div>
330
- <p className="text-fm-secondary text-sm">
331
- Bottom sheets work well for mobile-style interactions.
332
- </p>
333
- </div>
334
- </div>
335
- </SheetContent>
336
- </Sheet>
337
- </div>
183
+ {/* Variant types */}
184
+ <div className="space-y-3">
185
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
186
+ Semantic Variants
187
+ </h4>
188
+ <div className="flex flex-wrap gap-6">
189
+ <SideSheet
190
+ side="right"
191
+ variant="neutral"
192
+ label="Neutral"
193
+ description="Default neutral border accent."
194
+ />
195
+ <SideSheet
196
+ side="right"
197
+ variant="positive"
198
+ label="Positive"
199
+ description="Green border accent for success states."
200
+ />
201
+ <SideSheet
202
+ side="right"
203
+ variant="negative"
204
+ label="Negative"
205
+ description="Red border accent for error states."
206
+ />
207
+ <SideSheet
208
+ side="right"
209
+ variant="warning"
210
+ label="Warning"
211
+ description="Yellow border accent for cautionary states."
212
+ />
213
+ <SideSheet
214
+ side="right"
215
+ variant="info"
216
+ label="Info"
217
+ description="Blue border accent for informational states."
218
+ />
338
219
  </div>
220
+ </div>
339
221
 
340
- {/* Error Variant */}
341
- <div className="space-y-2">
342
- <h4 className="text-fm-secondary text-xs font-medium tracking-wide uppercase">
343
- Error Variant
344
- </h4>
345
- <Sheet>
346
- <SheetTrigger asChild>
347
- <Button size="sm" variant="outline">
348
- Error Sheet
349
- </Button>
350
- </SheetTrigger>
351
- <SheetContent side="right" variant="negative">
352
- <SheetHeader>
353
- <SheetTitle>Error Sheet</SheetTitle>
354
- <SheetDescription>
355
- Demonstrates the negative variant for error states
356
- </SheetDescription>
357
- </SheetHeader>
358
- <div className="py-4">
359
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
360
- <div className="mb-2 flex items-center gap-2">
361
- <AlertIcon className="text-fm-icon-negative h-5 w-5" />
362
- <h4 className="text-fm-primary font-medium">
363
- Error Details
364
- </h4>
365
- </div>
366
- <p className="text-fm-secondary mb-3 text-sm">
367
- Something went wrong. Please check the details below.
368
- </p>
369
- <div className="space-y-2">
370
- <div className="text-fm-secondary text-xs">
371
- • Network connection failed
372
- </div>
373
- <div className="text-fm-secondary text-xs">
374
- • Invalid response format
375
- </div>
376
- </div>
377
- </div>
378
- </div>
379
- <SheetFooter>
380
- <Button variant="outline" size="sm">
381
- Retry
382
- </Button>
383
- <SheetClose asChild>
384
- <Button size="sm">Close</Button>
385
- </SheetClose>
386
- </SheetFooter>
387
- </SheetContent>
388
- </Sheet>
222
+ {/* Overlay options */}
223
+ <div className="space-y-3">
224
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
225
+ Glass &amp; Noise Overlay Options
226
+ </h4>
227
+ <div className="flex flex-wrap gap-6">
228
+ <OverlaySheet label="Low opacity" opacity="low" />
229
+ <OverlaySheet label="High opacity" opacity="high" />
230
+ <OverlaySheet label="High glass" glass="high" />
231
+ <OverlaySheet label="Noise texture" noise="medium" />
389
232
  </div>
390
233
  </div>
391
234
  </div>
392
- </div>
393
- ),
235
+ )
236
+ },
394
237
  parameters: {
395
238
  docs: {
396
239
  description: {
397
240
  story:
398
- "Comprehensive demonstration of all sheet sides (left, right, top, bottom) and color variants (neutral, positive, negative, warning, info) with colored border accents.",
241
+ "Comparison of all four slide sides, all five semantic variants with gradient border accents, and overlay configuration options (opacity, glass, noise).",
399
242
  },
400
243
  },
401
244
  },
402
245
  }
403
246
 
404
- // 2. Navigation Sheet
405
- export const NavigationSheet: Story = {
406
- render: () => (
407
- <div className="relative">
408
- <BackgroundContent />
409
-
410
- {/* Mobile-style header */}
411
- <div className="fixed top-0 right-0 left-0 z-40 bg-black/80 backdrop-blur-sm">
412
- <div className="flex items-center justify-between p-4">
413
- <Sheet>
414
- <SheetTrigger asChild>
415
- <IconButton
416
- variant="ghost"
417
- icon={<SiteLogoIcon />}
418
- label="Menu"
419
- />
420
- </SheetTrigger>
421
- <SheetContent side="left" className="w-80">
422
- <SheetHeader>
423
- <SheetTitle>Navigation Menu</SheetTitle>
424
- <SheetDescription>
425
- Main navigation for the application
426
- </SheetDescription>
427
- </SheetHeader>
247
+ // ─── Interactive ───────────────────────────────────────────────────────────────
428
248
 
429
- <div className="py-4">
430
- <nav className="space-y-2">
431
- {[
432
- {
433
- label: "Dashboard",
434
- icon: SiteLogoIcon,
435
- active: true,
436
- badge: null,
437
- },
438
- {
439
- label: "Projects",
440
- icon: FeatureShineIcon,
441
- active: false,
442
- badge: "3",
443
- },
444
- {
445
- label: "Analytics",
446
- icon: FileChartIcon,
447
- active: false,
448
- badge: null,
449
- },
450
- {
451
- label: "Team",
452
- icon: TickCircleIcon,
453
- active: false,
454
- badge: "New",
455
- },
456
- {
457
- label: "Settings",
458
- icon: MaintenanceIcon,
459
- active: false,
460
- badge: null,
461
- },
462
- ].map((item) => (
463
- <a
464
- key={item.label}
465
- href="#"
466
- className={`flex items-center gap-3 rounded-lg p-3 transition-colors ${
467
- item.active
468
- ? "bg-fm-surface-info-sec text-fm-info"
469
- : "text-fm-primary hover:bg-fm-surface-secondary"
470
- }`}
471
- >
472
- <item.icon className="h-5 w-5" />
473
- <span className="flex-1">{item.label}</span>
474
- {item.badge && (
475
- <Badge
476
- color={item.badge === "New" ? "positive" : "neutral"}
477
- size="sm"
478
- >
479
- {item.badge}
480
- </Badge>
481
- )}
482
- <ChevronRightIcon className="h-4 w-4" />
483
- </a>
484
- ))}
485
- </nav>
249
+ export const Interactive: Story = {
250
+ render: () => {
251
+ const InteractiveDemo = () => {
252
+ const [side, setSide] = useState<"top" | "bottom" | "left" | "right">(
253
+ "right"
254
+ )
255
+ const [variant, setVariant] = useState<
256
+ "neutral" | "positive" | "negative" | "warning" | "info"
257
+ >("neutral")
258
+ const [opacity, setOpacity] = useState<
259
+ "high" | "medium" | "low" | "none"
260
+ >("medium")
261
+ const [glass, setGlass] = useState<"high" | "medium" | "low" | "none">(
262
+ "none"
263
+ )
264
+ const [noise, setNoise] = useState<"high" | "medium" | "low" | "none">(
265
+ "none"
266
+ )
267
+ const [lastAction, setLastAction] = useState<string | null>(null)
268
+
269
+ const sides = ["left", "right", "top", "bottom"] as const
270
+ const variants = [
271
+ "neutral",
272
+ "positive",
273
+ "negative",
274
+ "warning",
275
+ "info",
276
+ ] as const
277
+ const levels = ["none", "low", "medium", "high"] as const
278
+
279
+ const btnCls = (active: boolean) =>
280
+ `font-fm-text text-fm-sm leading-fm-sm rounded px-2 py-1 outline-none transition-colors ${
281
+ active
282
+ ? "bg-fm-surface-contrast text-fm-contrast"
283
+ : "bg-fm-surface-secondary text-fm-secondary hover:text-fm-primary"
284
+ }`
285
+
286
+ return (
287
+ <div className="w-full p-8">
288
+ <div className="mx-auto max-w-3xl space-y-6">
289
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
290
+ {/* Controls panel */}
291
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
292
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
293
+ Configuration
294
+ </p>
486
295
 
487
- <div className="mt-8 space-y-4">
488
- <div className="bg-fm-surface-secondary rounded-lg p-4">
489
- <h4 className="text-fm-primary mb-2 text-sm font-medium">
490
- Quick Actions
491
- </h4>
492
- <div className="space-y-2">
493
- <Button
494
- size="sm"
495
- variant="outline"
496
- className="w-full justify-start"
497
- >
498
- <SearchIcon className="mr-2 h-4 w-4" />
499
- Search
500
- </Button>
501
- <Button
502
- size="sm"
503
- variant="outline"
504
- className="w-full justify-start"
296
+ <div className="space-y-2">
297
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
298
+ Side
299
+ </p>
300
+ <div className="flex flex-wrap gap-1">
301
+ {sides.map((s) => (
302
+ <button
303
+ key={s}
304
+ onClick={() => setSide(s)}
305
+ className={btnCls(side === s)}
505
306
  >
506
- <MagicBookIcon className="mr-2 h-4 w-4" />
507
- Help & Support
508
- </Button>
509
- </div>
307
+ {s}
308
+ </button>
309
+ ))}
510
310
  </div>
511
311
  </div>
512
- </div>
513
312
 
514
- <SheetFooter>
515
- <div className="w-full space-y-2">
516
- <div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
517
- <div className="h-8 w-8 rounded-full bg-gradient-to-r from-blue-500 to-purple-500"></div>
518
- <div>
519
- <p className="text-fm-primary text-sm font-medium">
520
- John Doe
521
- </p>
522
- <p className="text-fm-secondary text-xs">
523
- john@example.com
524
- </p>
525
- </div>
313
+ <div className="border-fm-divider-secondary border-t pt-4" />
314
+
315
+ <div className="space-y-2">
316
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
317
+ Variant
318
+ </p>
319
+ <div className="flex flex-wrap gap-1">
320
+ {variants.map((v) => (
321
+ <button
322
+ key={v}
323
+ onClick={() => setVariant(v)}
324
+ className={btnCls(variant === v)}
325
+ >
326
+ {v}
327
+ </button>
328
+ ))}
526
329
  </div>
527
- <SheetClose asChild>
528
- <Button variant="outline" className="w-full">
529
- Close Menu
530
- </Button>
531
- </SheetClose>
532
330
  </div>
533
- </SheetFooter>
534
- </SheetContent>
535
- </Sheet>
536
-
537
- <h1 className="text-fm-primary text-lg font-semibold">App Title</h1>
538
331
 
539
- <IconButton
540
- variant="ghost"
541
- icon={<MaintenanceIcon />}
542
- label="Settings"
543
- />
544
- </div>
545
- </div>
332
+ <div className="border-fm-divider-secondary border-t pt-4" />
546
333
 
547
- {/* Add padding top to account for fixed header */}
548
- <div className="pt-16">
549
- <BackgroundContent />
550
- </div>
551
- </div>
552
- ),
553
- parameters: {
554
- docs: {
555
- description: {
556
- story:
557
- "Mobile-style navigation sheet with menu items, badges, user profile, and quick actions demonstrating common mobile app patterns.",
558
- },
559
- },
560
- },
561
- }
562
-
563
- // 3. Form Sheet
564
- export const FormSheet: Story = {
565
- render: () => {
566
- const [formData, setFormData] = useState({
567
- name: "",
568
- email: "",
569
- subject: "",
570
- message: "",
571
- newsletter: false,
572
- })
573
-
574
- return (
575
- <div className="relative">
576
- <BackgroundContent />
577
-
578
- <div className="fixed right-4 bottom-4 z-50">
579
- <Sheet>
580
- <SheetTrigger asChild>
581
- <Button className="rounded-full shadow-lg">
582
- <SearchIcon className="mr-2 h-4 w-4" />
583
- Contact Us
584
- </Button>
585
- </SheetTrigger>
586
- <SheetContent side="right" className="w-96">
587
- <SheetHeader>
588
- <SheetTitle>Contact Form</SheetTitle>
589
- <SheetDescription>
590
- Send us a message and we'll get back to you soon.
591
- </SheetDescription>
592
- </SheetHeader>
593
-
594
- <div className="py-4">
595
- <form className="space-y-4">
596
- <div className="space-y-2">
597
- <Label htmlFor="name">Name</Label>
598
- <Input
599
- id="name"
600
- placeholder="Your full name"
601
- value={formData.name}
602
- onChange={(e: any) =>
603
- setFormData((prev) => ({
604
- ...prev,
605
- name: e.target.value,
606
- }))
607
- }
608
- />
334
+ <div className="space-y-2">
335
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
336
+ Opacity
337
+ </p>
338
+ <div className="flex flex-wrap gap-1">
339
+ {levels.map((l) => (
340
+ <button
341
+ key={l}
342
+ onClick={() => setOpacity(l)}
343
+ className={btnCls(opacity === l)}
344
+ >
345
+ {l}
346
+ </button>
347
+ ))}
609
348
  </div>
349
+ </div>
610
350
 
611
- <div className="space-y-2">
612
- <Label htmlFor="email">Email</Label>
613
- <Input
614
- id="email"
615
- type="email"
616
- placeholder="your.email@example.com"
617
- value={formData.email}
618
- onChange={(e: any) =>
619
- setFormData((prev) => ({
620
- ...prev,
621
- email: e.target.value,
622
- }))
623
- }
624
- />
351
+ <div className="space-y-2">
352
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
353
+ Glass
354
+ </p>
355
+ <div className="flex flex-wrap gap-1">
356
+ {levels.map((l) => (
357
+ <button
358
+ key={l}
359
+ onClick={() => setGlass(l)}
360
+ className={btnCls(glass === l)}
361
+ >
362
+ {l}
363
+ </button>
364
+ ))}
625
365
  </div>
366
+ </div>
626
367
 
627
- <div className="space-y-2">
628
- <Label htmlFor="subject">Subject</Label>
629
- <Input
630
- id="subject"
631
- placeholder="Message subject"
632
- value={formData.subject}
633
- onChange={(e: any) =>
634
- setFormData((prev) => ({
635
- ...prev,
636
- subject: e.target.value,
637
- }))
638
- }
639
- />
368
+ <div className="space-y-2">
369
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
370
+ Noise
371
+ </p>
372
+ <div className="flex flex-wrap gap-1">
373
+ {levels.map((l) => (
374
+ <button
375
+ key={l}
376
+ onClick={() => setNoise(l)}
377
+ className={btnCls(noise === l)}
378
+ >
379
+ {l}
380
+ </button>
381
+ ))}
640
382
  </div>
383
+ </div>
384
+ </div>
641
385
 
642
- <div className="space-y-2">
643
- <Label htmlFor="message">Message</Label>
644
- <Textarea
645
- id="message"
646
- placeholder="Your message..."
647
- rows={4}
648
- value={formData.message}
649
- onChange={(e: any) =>
650
- setFormData((prev) => ({
651
- ...prev,
652
- message: e.target.value,
653
- }))
654
- }
655
- />
656
- </div>
386
+ {/* Preview stage */}
387
+ <div className="flex flex-col gap-3 lg:col-span-2">
388
+ <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">
389
+ {lastAction && (
390
+ <div
391
+ className={`rounded-lg border px-4 py-2 ${
392
+ lastAction === "confirmed"
393
+ ? "border-fm-divider-positive bg-fm-surface-positive-sec"
394
+ : "border-fm-divider-secondary bg-fm-surface-secondary"
395
+ }`}
396
+ >
397
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
398
+ Last action:{" "}
399
+ <span className="text-fm-primary font-medium">
400
+ {lastAction}
401
+ </span>
402
+ </p>
403
+ </div>
404
+ )}
657
405
 
658
- <div className="flex items-center space-x-2">
659
- <Checkbox
660
- id="newsletter"
661
- checked={formData.newsletter}
662
- onCheckedChange={(checked) =>
663
- setFormData((prev) => ({
664
- ...prev,
665
- newsletter: checked as boolean,
666
- }))
667
- }
668
- />
669
- <Label htmlFor="newsletter" className="text-sm">
670
- Subscribe to newsletter
671
- </Label>
672
- </div>
406
+ <Sheet>
407
+ <SheetTrigger asChild>
408
+ <Button onClick={() => setLastAction(null)}>
409
+ Open Sheet
410
+ </Button>
411
+ </SheetTrigger>
412
+ <SheetContent
413
+ side={side}
414
+ variant={variant}
415
+ opacity={opacity}
416
+ glass={glass}
417
+ noise={noise}
418
+ container={null}
419
+ >
420
+ <SheetHeader>
421
+ <SheetTitle>Sheet Preview</SheetTitle>
422
+ <SheetDescription>
423
+ Interact with content inside the sheet, then confirm
424
+ or cancel.
425
+ </SheetDescription>
426
+ </SheetHeader>
427
+
428
+ <div className="py-4">
429
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
430
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
431
+ {`side="${side}" variant="${variant}" opacity="${opacity}" glass="${glass}" noise="${noise}"`}
432
+ </code>
433
+ </div>
434
+ </div>
673
435
 
674
- <div className="bg-fm-surface-info-sec rounded-lg p-3">
675
- <p className="text-fm-info text-xs">
676
- We typically respond within 24 hours. For urgent matters,
677
- please call our support line.
678
- </p>
679
- </div>
680
- </form>
681
- </div>
436
+ <SheetFooter>
437
+ <Button
438
+ variant="outline"
439
+ onClick={() => setLastAction("cancelled")}
440
+ >
441
+ Cancel
442
+ </Button>
443
+ <SheetClose asChild>
444
+ <Button onClick={() => setLastAction("confirmed")}>
445
+ Confirm
446
+ </Button>
447
+ </SheetClose>
448
+ </SheetFooter>
449
+ </SheetContent>
450
+ </Sheet>
451
+ </div>
682
452
 
683
- <SheetFooter>
684
- <div className="flex w-full gap-2">
685
- <SheetClose asChild>
686
- <Button variant="outline" className="flex-1">
687
- Cancel
688
- </Button>
689
- </SheetClose>
690
- <Button
691
- className="flex-1"
692
- disabled={
693
- !formData.name || !formData.email || !formData.message
694
- }
695
- >
696
- Send Message
697
- </Button>
453
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
454
+ <code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
455
+ {`<SheetContent side="${side}" variant="${variant}" opacity="${opacity}" glass="${glass}" noise="${noise}" />`}
456
+ </code>
698
457
  </div>
699
- </SheetFooter>
700
- </SheetContent>
701
- </Sheet>
458
+ </div>
459
+ </div>
460
+ </div>
702
461
  </div>
703
- </div>
704
- )
462
+ )
463
+ }
464
+
465
+ return <InteractiveDemo />
705
466
  },
706
467
  parameters: {
707
468
  docs: {
708
469
  description: {
709
470
  story:
710
- "Contact form sheet with form validation, checkbox input, and user feedback elements.",
471
+ "Live configurator pick side, variant, opacity, glass, and noise, then open the sheet and confirm or cancel to see state feedback.",
711
472
  },
712
473
  },
713
474
  },
714
475
  }
715
476
 
716
- // 4. Settings Panel Sheet
717
- export const SettingsPanelSheet: Story = {
718
- render: () => {
719
- const [settings, setSettings] = useState({
720
- notifications: true,
721
- darkMode: true,
722
- analytics: false,
723
- autoSave: true,
724
- emailUpdates: false,
725
- })
726
-
727
- const toggleSetting = (key: string) => {
728
- setSettings((prev) => ({
729
- ...prev,
730
- [key]: !prev[key as keyof typeof prev],
731
- }))
732
- }
733
-
734
- return (
735
- <div className="relative">
736
- <BackgroundContent />
737
-
738
- <div className="fixed top-4 right-4 z-50">
739
- <Sheet>
740
- <SheetTrigger asChild>
741
- <Button variant="outline">
742
- <MaintenanceIcon className="mr-2 h-4 w-4" />
743
- Settings
744
- </Button>
745
- </SheetTrigger>
746
- <SheetContent side="right" className="w-80">
747
- <SheetHeader>
748
- <SheetTitle>Application Settings</SheetTitle>
749
- <SheetDescription>
750
- Customize your experience and preferences
751
- </SheetDescription>
752
- </SheetHeader>
753
-
754
- <div className="py-4">
755
- <div className="space-y-6">
756
- {/* Notifications Section */}
757
- <div className="space-y-3">
758
- <h4 className="text-fm-primary text-sm font-medium">
759
- Notifications
760
- </h4>
761
- <div className="space-y-3">
762
- <div className="flex items-center justify-between">
763
- <span className="text-fm-primary text-sm">
764
- Push Notifications
765
- </span>
766
- <Checkbox
767
- checked={settings.notifications}
768
- onCheckedChange={() => toggleSetting("notifications")}
769
- />
770
- </div>
771
-
772
- <div className="flex items-center justify-between">
773
- <span className="text-fm-primary text-sm">
774
- Email Updates
775
- </span>
776
- <Checkbox
777
- checked={settings.emailUpdates}
778
- onCheckedChange={() => toggleSetting("emailUpdates")}
779
- />
780
- </div>
781
-
782
- <div className="flex items-center justify-between">
783
- <span className="text-fm-primary text-sm">
784
- Analytics
785
- </span>
786
- <Checkbox
787
- checked={settings.analytics}
788
- onCheckedChange={() => toggleSetting("analytics")}
789
- />
790
- </div>
791
- </div>
792
- </div>
477
+ // ─── UseCases ─────────────────────────────────────────────────────────────────
793
478
 
794
- {/* Appearance Section */}
795
- <div className="space-y-3">
796
- <h4 className="text-fm-primary text-sm font-medium">
797
- Appearance
798
- </h4>
799
- <div className="space-y-3">
800
- <div className="flex items-center justify-between">
801
- <span className="text-fm-primary text-sm">
802
- Dark Mode
803
- </span>
804
- <Checkbox
805
- checked={settings.darkMode}
806
- onCheckedChange={() => toggleSetting("darkMode")}
807
- />
808
- </div>
479
+ export const UseCases: Story = {
480
+ render: () => {
481
+ // Left: Filter panel
482
+ const FilterPanel = () => {
483
+ const [genre, setGenre] = useState<string[]>([])
484
+ const [mood, setMood] = useState<string[]>([])
485
+
486
+ const toggleFilter = (
487
+ list: string[],
488
+ set: (v: string[]) => void,
489
+ item: string
490
+ ) => {
491
+ set(
492
+ list.includes(item) ? list.filter((i) => i !== item) : [...list, item]
493
+ )
494
+ }
495
+
496
+ const genres = ["Lo-fi", "Jazz", "Electronic", "Acoustic", "Classical"]
497
+ const moods = ["Chill", "Focus", "Energetic", "Melancholic"]
498
+
499
+ return (
500
+ <Sheet>
501
+ <SheetTrigger asChild>
502
+ <Button variant="outline" size="sm">
503
+ Filter panel
504
+ </Button>
505
+ </SheetTrigger>
506
+ <SheetContent side="left" variant="neutral" container={null}>
507
+ <SheetHeader>
508
+ <SheetTitle>Filter Tracks</SheetTitle>
509
+ <SheetDescription>
510
+ Narrow your library by genre and mood.
511
+ </SheetDescription>
512
+ </SheetHeader>
513
+
514
+ <div className="space-y-6 py-4">
515
+ <div className="space-y-3">
516
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
517
+ Genre
518
+ </p>
519
+ <div className="space-y-2">
520
+ {genres.map((g) => (
521
+ <div key={g} className="flex items-center gap-3">
522
+ <Checkbox
523
+ id={`genre-${g}`}
524
+ checked={genre.includes(g)}
525
+ onCheckedChange={() => toggleFilter(genre, setGenre, g)}
526
+ />
527
+ <Label
528
+ htmlFor={`genre-${g}`}
529
+ className="text-fm-primary font-fm-text text-fm-md leading-fm-md"
530
+ >
531
+ {g}
532
+ </Label>
809
533
  </div>
810
- </div>
811
-
812
- {/* Advanced Section */}
813
- <div className="space-y-3">
814
- <h4 className="text-fm-primary text-sm font-medium">
815
- Advanced
816
- </h4>
817
- <div className="space-y-3">
818
- <div className="flex items-center justify-between">
819
- <span className="text-fm-primary text-sm">
820
- Auto Save
821
- </span>
822
- <Checkbox
823
- checked={settings.autoSave}
824
- onCheckedChange={() => toggleSetting("autoSave")}
825
- />
826
- </div>
534
+ ))}
535
+ </div>
536
+ </div>
827
537
 
828
- <Button variant="outline" size="sm" className="w-full">
829
- <FileChartIcon className="mr-2 h-4 w-4" />
830
- Clear Cache
831
- </Button>
538
+ <div className="border-fm-divider-secondary border-t" />
832
539
 
833
- <Button variant="outline" size="sm" className="w-full">
834
- <ArrowRightIcon className="mr-2 h-4 w-4" />
835
- Export Data
836
- </Button>
540
+ <div className="space-y-3">
541
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
542
+ Mood
543
+ </p>
544
+ <div className="space-y-2">
545
+ {moods.map((m) => (
546
+ <div key={m} className="flex items-center gap-3">
547
+ <Checkbox
548
+ id={`mood-${m}`}
549
+ checked={mood.includes(m)}
550
+ onCheckedChange={() => toggleFilter(mood, setMood, m)}
551
+ />
552
+ <Label
553
+ htmlFor={`mood-${m}`}
554
+ className="text-fm-primary font-fm-text text-fm-md leading-fm-md"
555
+ >
556
+ {m}
557
+ </Label>
837
558
  </div>
838
- </div>
559
+ ))}
839
560
  </div>
840
561
  </div>
841
562
 
842
- <SheetFooter>
843
- <div className="flex w-full gap-2">
844
- <Button variant="outline" size="sm" className="flex-1">
845
- Reset
846
- </Button>
847
- <SheetClose asChild>
848
- <Button size="sm" className="flex-1">
849
- Save Changes
850
- </Button>
851
- </SheetClose>
563
+ {(genre.length > 0 || mood.length > 0) && (
564
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
565
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
566
+ Active filters:{" "}
567
+ <span className="text-fm-primary font-medium">
568
+ {[...genre, ...mood].join(", ")}
569
+ </span>
570
+ </p>
852
571
  </div>
853
- </SheetFooter>
854
- </SheetContent>
855
- </Sheet>
856
- </div>
857
- </div>
858
- )
859
- },
860
- parameters: {
861
- docs: {
862
- description: {
863
- story:
864
- "Settings panel sheet with checkboxes, sections, and action buttons demonstrating configuration interfaces.",
865
- },
866
- },
867
- },
868
- }
572
+ )}
573
+ </div>
869
574
 
870
- // 5. Overlay Variations
871
- export const OverlayVariations: Story = {
872
- render: () => (
873
- <div className="relative">
874
- <BackgroundContent />
575
+ <SheetFooter>
576
+ <Button
577
+ variant="outline"
578
+ onClick={() => {
579
+ setGenre([])
580
+ setMood([])
581
+ }}
582
+ >
583
+ Clear all
584
+ </Button>
585
+ <SheetClose asChild>
586
+ <Button>Apply filters</Button>
587
+ </SheetClose>
588
+ </SheetFooter>
589
+ </SheetContent>
590
+ </Sheet>
591
+ )
592
+ }
875
593
 
876
- <div className="fixed bottom-4 left-1/2 z-50 -translate-x-1/2 transform">
877
- <div className="space-y-2 rounded-lg bg-black/80 p-4 backdrop-blur-sm">
878
- <h3 className="text-fm-primary text-center text-sm font-medium">
879
- Overlay Variations
880
- </h3>
881
- <div className="flex gap-2">
882
- {/* Low Opacity */}
883
- <Sheet>
884
- <SheetTrigger asChild>
885
- <Button size="sm" variant="outline">
886
- Low Opacity
887
- </Button>
888
- </SheetTrigger>
889
- <SheetContent side="right" opacity="low">
890
- <SheetHeader>
891
- <SheetTitle>Low Opacity</SheetTitle>
892
- <SheetDescription>
893
- Subtle background overlay that maintains visibility
894
- </SheetDescription>
895
- </SheetHeader>
896
- <div className="py-4">
897
- <p className="text-fm-secondary text-sm">
898
- This sheet uses low opacity overlay, allowing more of the
899
- background content to remain visible.
900
- </p>
901
- </div>
902
- </SheetContent>
903
- </Sheet>
594
+ // Right: Track details
595
+ const TrackDetails = () => {
596
+ const [liked, setLiked] = useState(false)
597
+ const [queued, setQueued] = useState(false)
904
598
 
905
- {/* High Opacity */}
906
- <Sheet>
907
- <SheetTrigger asChild>
908
- <Button size="sm" variant="outline">
909
- High Opacity
910
- </Button>
911
- </SheetTrigger>
912
- <SheetContent side="right" opacity="high">
913
- <SheetHeader>
914
- <SheetTitle>High Opacity</SheetTitle>
915
- <SheetDescription>
916
- Strong background overlay for maximum focus
917
- </SheetDescription>
918
- </SheetHeader>
919
- <div className="py-4">
920
- <p className="text-fm-secondary text-sm">
921
- This sheet uses high opacity overlay, creating strong focus
922
- on the sheet content by dimming the background
923
- significantly.
924
- </p>
925
- </div>
926
- </SheetContent>
927
- </Sheet>
599
+ return (
600
+ <Sheet>
601
+ <SheetTrigger asChild>
602
+ <Button variant="outline" size="sm">
603
+ Track details
604
+ </Button>
605
+ </SheetTrigger>
606
+ <SheetContent side="right" variant="info" container={null}>
607
+ <SheetHeader>
608
+ <SheetTitle>Midnight Drive</SheetTitle>
609
+ <SheetDescription>
610
+ Lo-fi Chill · Album: Late Nights · 3:42
611
+ </SheetDescription>
612
+ </SheetHeader>
613
+
614
+ <div className="space-y-4 py-4">
615
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
616
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold tracking-widest uppercase">
617
+ About this track
618
+ </p>
619
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
620
+ A smooth lo-fi track perfect for late-night focus sessions.
621
+ Released in 2024 as part of the Late Nights collection.
622
+ </p>
623
+ </div>
928
624
 
929
- {/* Glass Effect */}
930
- <Sheet>
931
- <SheetTrigger asChild>
932
- <Button size="sm" variant="outline">
933
- Glass Effect
934
- </Button>
935
- </SheetTrigger>
936
- <SheetContent side="right" glass="high">
937
- <SheetHeader>
938
- <SheetTitle>Glass Effect</SheetTitle>
939
- <SheetDescription>
940
- Frosted glass overlay for modern aesthetics
941
- </SheetDescription>
942
- </SheetHeader>
943
- <div className="py-4">
944
- <p className="text-fm-secondary text-sm">
945
- This sheet includes a glass effect with backdrop blur,
946
- creating a modern frosted glass appearance.
947
- </p>
948
- </div>
949
- </SheetContent>
950
- </Sheet>
625
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-3 rounded-lg border p-4">
626
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
627
+ Track info
628
+ </p>
629
+ {[
630
+ { label: "Artist", value: "Chill Collective" },
631
+ { label: "BPM", value: "85" },
632
+ { label: "Key", value: "F Minor" },
633
+ { label: "Plays", value: "124,381" },
634
+ ].map((row) => (
635
+ <div
636
+ key={row.label}
637
+ className="flex items-center justify-between"
638
+ >
639
+ <span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
640
+ {row.label}
641
+ </span>
642
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm font-medium">
643
+ {row.value}
644
+ </span>
645
+ </div>
646
+ ))}
647
+ </div>
951
648
 
952
- {/* Noise Texture */}
953
- <Sheet>
954
- <SheetTrigger asChild>
955
- <Button size="sm" variant="outline">
956
- Noise Texture
649
+ <div className="flex gap-2">
650
+ <Button
651
+ variant="outline"
652
+ size="sm"
653
+ className="flex-1 gap-2"
654
+ onClick={() => setLiked((v) => !v)}
655
+ >
656
+ <TickCircleIcon className="h-4 w-4" />
657
+ {liked ? "Liked" : "Like"}
957
658
  </Button>
958
- </SheetTrigger>
959
- <SheetContent side="right" noise="medium">
960
- <SheetHeader>
961
- <SheetTitle>Noise Texture</SheetTitle>
962
- <SheetDescription>
963
- Textured overlay for enhanced visual depth
964
- </SheetDescription>
965
- </SheetHeader>
966
- <div className="py-4">
967
- <p className="text-fm-secondary text-sm">
968
- This sheet includes noise texture overlay, adding visual
969
- interest and depth to the background.
970
- </p>
971
- </div>
972
- </SheetContent>
973
- </Sheet>
974
- </div>
975
- </div>
976
- </div>
977
- </div>
978
- ),
979
- parameters: {
980
- docs: {
981
- description: {
982
- story:
983
- "Different overlay configurations showing opacity levels, glass effects, and noise textures for various visual requirements.",
984
- },
985
- },
986
- },
987
- }
659
+ <Button
660
+ variant="outline"
661
+ size="sm"
662
+ className="flex-1 gap-2"
663
+ onClick={() => setQueued((v) => !v)}
664
+ >
665
+ <MusicalNoteIcon className="h-4 w-4" />
666
+ {queued ? "In queue" : "Add to queue"}
667
+ </Button>
668
+ </div>
669
+ </div>
988
670
 
989
- // 6. Mobile Bottom Sheet
990
- export const MobileBottomSheet: Story = {
991
- render: () => {
992
- const [selectedOption, setSelectedOption] = useState<string | null>(null)
671
+ <SheetFooter>
672
+ <SheetClose asChild>
673
+ <Button variant="outline">Close</Button>
674
+ </SheetClose>
675
+ <Button>Play now</Button>
676
+ </SheetFooter>
677
+ </SheetContent>
678
+ </Sheet>
679
+ )
680
+ }
993
681
 
994
- return (
995
- <div className="relative">
996
- <BackgroundContent />
682
+ // Bottom: Quick action sheet
683
+ const QuickActions = () => {
684
+ const [search, setSearch] = useState("")
685
+ const actions = [
686
+ { label: "Add to playlist", icon: MusicalNoteIcon },
687
+ { label: "Go to artist", icon: ChevronRightIcon },
688
+ { label: "Find similar tracks", icon: SearchIcon },
689
+ { label: "Report issue", icon: AlertIcon },
690
+ { label: "Share", icon: SiteLogoIcon },
691
+ { label: "Settings", icon: MaintenanceIcon },
692
+ ]
693
+ const filtered = actions.filter((a) =>
694
+ a.label.toLowerCase().includes(search.toLowerCase())
695
+ )
696
+
697
+ return (
698
+ <Sheet>
699
+ <SheetTrigger asChild>
700
+ <Button variant="outline" size="sm">
701
+ Quick actions
702
+ </Button>
703
+ </SheetTrigger>
704
+ <SheetContent side="bottom" variant="neutral" container={null}>
705
+ <SheetHeader>
706
+ <SheetTitle>Quick Actions</SheetTitle>
707
+ <SheetDescription>
708
+ Search and pick an action for this track.
709
+ </SheetDescription>
710
+ </SheetHeader>
711
+
712
+ <div className="space-y-4 py-4">
713
+ <Input
714
+ placeholder="Search actions..."
715
+ value={search}
716
+ onChange={(e) => setSearch(e.target.value)}
717
+ />
718
+ <div className="space-y-1">
719
+ {filtered.length === 0 && (
720
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm py-2 text-center">
721
+ No actions match your search.
722
+ </p>
723
+ )}
724
+ {filtered.map((action) => (
725
+ <button
726
+ key={action.label}
727
+ className="text-fm-primary hover:bg-fm-surface-secondary flex w-full items-center gap-3 rounded-lg px-3 py-3 text-left transition-colors"
728
+ >
729
+ <action.icon className="text-fm-secondary h-5 w-5 shrink-0" />
730
+ <span className="font-fm-text text-fm-md leading-fm-md">
731
+ {action.label}
732
+ </span>
733
+ </button>
734
+ ))}
735
+ </div>
736
+ </div>
997
737
 
998
- {/* Simulate mobile content */}
999
- <div className="fixed bottom-4 left-1/2 z-50 -translate-x-1/2 transform">
1000
- <Sheet>
1001
- <SheetTrigger asChild>
1002
- <Button>Share Options</Button>
1003
- </SheetTrigger>
1004
- <SheetContent side="bottom" className="h-auto max-h-96">
1005
- <SheetHeader>
1006
- <SheetTitle>Share</SheetTitle>
1007
- <SheetDescription>
1008
- Choose how you'd like to share this content
1009
- </SheetDescription>
1010
- </SheetHeader>
738
+ <SheetFooter>
739
+ <SheetClose asChild>
740
+ <Button variant="outline" className="w-full">
741
+ Dismiss
742
+ </Button>
743
+ </SheetClose>
744
+ </SheetFooter>
745
+ </SheetContent>
746
+ </Sheet>
747
+ )
748
+ }
1011
749
 
1012
- <div className="py-4">
1013
- <div className="mb-6 grid grid-cols-4 gap-4">
1014
- {[
1015
- { name: "Message", icon: SearchIcon },
1016
- { name: "Email", icon: AlertIcon },
1017
- { name: "Copy Link", icon: TickCircleIcon },
1018
- { name: "More", icon: SiteLogoIcon },
1019
- ].map((option) => (
1020
- <button
1021
- key={option.name}
1022
- onClick={() => setSelectedOption(option.name)}
1023
- className={`flex flex-col items-center gap-2 rounded-lg p-3 transition-colors ${
1024
- selectedOption === option.name
1025
- ? "bg-fm-surface-info-sec text-fm-info"
1026
- : "text-fm-primary hover:bg-fm-surface-secondary"
1027
- }`}
1028
- >
1029
- <option.icon className="h-6 w-6" />
1030
- <span className="text-xs">{option.name}</span>
1031
- </button>
1032
- ))}
1033
- </div>
750
+ return (
751
+ <div className="mx-auto max-w-3xl space-y-8 p-8">
752
+ <div className="space-y-3">
753
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
754
+ Filter Panel Left Side
755
+ </h4>
756
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
757
+ A left-side filter panel for narrowing a music library by genre and
758
+ mood. Selected filters are summarised and can be cleared.
759
+ </p>
760
+ <FilterPanel />
761
+ </div>
1034
762
 
1035
- <div className="space-y-2">
1036
- <h4 className="text-fm-primary text-sm font-medium">
1037
- Recent Contacts
1038
- </h4>
1039
- {Array.from({ length: 3 }, (_, i) => (
1040
- <div
1041
- key={i}
1042
- className="hover:bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-2"
1043
- >
1044
- <div className="h-8 w-8 rounded-full bg-gradient-to-r from-blue-500 to-purple-500"></div>
1045
- <span className="text-fm-primary text-sm">
1046
- Contact {i + 1}
1047
- </span>
1048
- </div>
1049
- ))}
1050
- </div>
1051
- </div>
763
+ <div className="space-y-3">
764
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
765
+ Track Details — Right Side
766
+ </h4>
767
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
768
+ A right-side detail panel showing metadata, stats, and contextual
769
+ actions for the currently selected track.
770
+ </p>
771
+ <TrackDetails />
772
+ </div>
1052
773
 
1053
- <SheetFooter>
1054
- <SheetClose asChild>
1055
- <Button variant="outline" className="w-full">
1056
- Cancel
1057
- </Button>
1058
- </SheetClose>
1059
- </SheetFooter>
1060
- </SheetContent>
1061
- </Sheet>
774
+ <div className="space-y-3">
775
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
776
+ Quick Action Sheet — Bottom
777
+ </h4>
778
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
779
+ A searchable bottom action sheet for quickly finding and triggering
780
+ contextual commands on a track.
781
+ </p>
782
+ <QuickActions />
1062
783
  </div>
1063
784
  </div>
1064
785
  )
@@ -1067,7 +788,7 @@ export const MobileBottomSheet: Story = {
1067
788
  docs: {
1068
789
  description: {
1069
790
  story:
1070
- "Mobile-style bottom sheet with share options and contact list, demonstrating common mobile interaction patterns.",
791
+ "Three realistic product scenarios: a left filter panel for library browsing, a right track-details panel, and a searchable bottom quick-action sheet.",
1071
792
  },
1072
793
  },
1073
794
  },