aural-ui 3.0.7 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1199
  2. package/dist/components/avatar/Avatar.stories.tsx +235 -237
  3. package/dist/components/badge/Badge.stories.tsx +379 -116
  4. package/dist/components/banner/Banner.stories.tsx +445 -391
  5. package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
  6. package/dist/components/button/Button.stories.tsx +585 -230
  7. package/dist/components/button/index.tsx +7 -7
  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 -620
  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 +533 -856
  16. package/dist/components/dialog/Dialog.stories.tsx +505 -949
  17. package/dist/components/divider/Divider.stories.tsx +265 -502
  18. package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
  19. package/dist/components/drawer/Drawer.stories.tsx +659 -993
  20. package/dist/components/drawer/index.tsx +3 -3
  21. package/dist/components/dropdown/Dropdown.stories.tsx +643 -1018
  22. package/dist/components/form/Form.stories.tsx +560 -274
  23. package/dist/components/helper-text/HelperText.stories.tsx +199 -200
  24. package/dist/components/hover-card/HoverCard.stories.tsx +318 -1221
  25. package/dist/components/icon-button/IconButton.stories.tsx +837 -194
  26. package/dist/components/if-else/if-else.stories.tsx +370 -83
  27. package/dist/components/input/Input.stories.tsx +436 -368
  28. package/dist/components/label/Label.stories.tsx +156 -154
  29. package/dist/components/list/List.stories.tsx +485 -822
  30. package/dist/components/marquee/Marquee.stories.tsx +356 -694
  31. package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -410
  32. package/dist/components/overlay/Overlay.stories.tsx +452 -818
  33. package/dist/components/overlay/index.tsx +4 -4
  34. package/dist/components/pagination/Pagination.stories.tsx +721 -210
  35. package/dist/components/popover/Popover.stories.tsx +484 -873
  36. package/dist/components/radio/Radio.stories.tsx +432 -124
  37. package/dist/components/resizable/Resizable.stories.tsx +496 -752
  38. package/dist/components/scroll-area/ScrollArea.stories.tsx +384 -1006
  39. package/dist/components/search/Search.stories.tsx +314 -575
  40. package/dist/components/select/Select.stories.tsx +684 -787
  41. package/dist/components/sheet/Sheet.stories.tsx +671 -936
  42. package/dist/components/skelton/Skelton.stories.tsx +230 -764
  43. package/dist/components/slider/Slider.stories.tsx +384 -737
  44. package/dist/components/stepper/Stepper.stories.tsx +371 -514
  45. package/dist/components/switch/Switch.stories.tsx +461 -208
  46. package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
  47. package/dist/components/table/Table.stories.tsx +770 -914
  48. package/dist/components/tabs/Tabs.stories.tsx +459 -1400
  49. package/dist/components/tag/Tag.stories.tsx +714 -542
  50. package/dist/components/textarea/TextArea.stories.tsx +621 -562
  51. package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -148
  52. package/dist/components/toast/Toast.stories.tsx +452 -1333
  53. package/dist/components/toggle/Toggle.stories.tsx +488 -909
  54. package/dist/components/tooltip/Tooltip.stories.tsx +344 -1372
  55. package/dist/components/typography/Typography.stories.tsx +406 -89
  56. package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
  57. package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
  58. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
  59. package/dist/icons/Icons.stories.tsx +0 -12
  60. package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +226 -1013
  61. package/dist/icons/alert-icon/AlertIcon.stories.tsx +109 -929
  62. package/dist/icons/all-icons.tsx +124 -87
  63. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +140 -971
  64. package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +148 -888
  65. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +135 -1019
  66. package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +137 -953
  67. package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +138 -997
  68. package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +136 -942
  69. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +148 -1092
  70. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +146 -1211
  71. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +126 -615
  72. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +144 -1164
  73. package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +167 -985
  74. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +122 -1179
  75. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +124 -1168
  76. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +119 -850
  77. package/dist/icons/camera-icon/CameraIcon.stories.tsx +112 -1213
  78. package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +117 -934
  79. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +160 -961
  80. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +163 -961
  81. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +144 -942
  82. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +129 -966
  83. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +147 -964
  84. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +145 -975
  85. package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +150 -1142
  86. package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +114 -461
  87. package/dist/icons/coin-icon/CoinIcon.stories.tsx +124 -1322
  88. package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +117 -1318
  89. package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +114 -903
  90. package/dist/icons/command-icon/CommandIcon.stories.tsx +127 -1042
  91. package/dist/icons/copy-icon/CopyIcon.stories.tsx +123 -962
  92. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +147 -999
  93. package/dist/icons/cross-icon/CrossIcon.stories.tsx +139 -960
  94. package/dist/icons/download-icon/DownloadIcon.stories.tsx +126 -820
  95. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +124 -1031
  96. package/dist/icons/email-icon/EmailIcon.stories.tsx +115 -936
  97. package/dist/icons/expand-icon/ExpandIcon.stories.tsx +112 -1111
  98. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +144 -1025
  99. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +143 -1036
  100. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +127 -1011
  101. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +126 -1056
  102. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +125 -614
  103. package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +119 -1050
  104. package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +169 -989
  105. package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +115 -1145
  106. package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +115 -1122
  107. package/dist/icons/globe-icon/GlobeIcon.stories.tsx +130 -313
  108. package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +145 -940
  109. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +119 -1174
  110. package/dist/icons/head-icon/HeadIcon.stories.tsx +111 -916
  111. package/dist/icons/heart-icon/HeartIcon.stories.tsx +120 -1019
  112. package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +119 -683
  113. package/dist/icons/image-icon/ImageIcon.stories.tsx +105 -1121
  114. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +111 -1192
  115. package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +136 -1256
  116. package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +159 -962
  117. package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +161 -1385
  118. package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +124 -972
  119. package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +119 -948
  120. package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +119 -942
  121. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +108 -1215
  122. package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +154 -1517
  123. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +110 -1188
  124. package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +119 -678
  125. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +123 -1184
  126. package/dist/icons/message-icon/MessageIcon.stories.tsx +114 -538
  127. package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +116 -1158
  128. package/dist/icons/moon-icon/MoonIcon.stories.tsx +120 -536
  129. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +109 -1184
  130. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +115 -1134
  131. package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +119 -971
  132. package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +111 -1100
  133. package/dist/icons/notes-icon/NotesIcon.stories.tsx +119 -1101
  134. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +109 -1111
  135. package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +122 -684
  136. package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +113 -954
  137. package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +112 -877
  138. package/dist/icons/pause-icon/PauseIcon.stories.tsx +113 -1000
  139. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +115 -1070
  140. package/dist/icons/phone-icon/PhoneIcon.stories.tsx +115 -978
  141. package/dist/icons/plus-icon/PlusIcon.stories.tsx +106 -1093
  142. package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +107 -829
  143. package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +102 -469
  144. package/dist/icons/search-icon/SearchIcon.stories.tsx +111 -1124
  145. package/dist/icons/setting-icon/SettingIcon.stories.tsx +107 -970
  146. package/dist/icons/share-icon/ShareIcon.stories.tsx +120 -1025
  147. package/dist/icons/shield-icon/ShieldIcon.stories.tsx +117 -931
  148. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +137 -1104
  149. package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +172 -982
  150. package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +164 -983
  151. package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +105 -958
  152. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +158 -580
  153. package/dist/icons/spinner-gradient-icon/index.tsx +6 -1
  154. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +158 -587
  155. package/dist/icons/spinner-solid-icon/index.tsx +6 -1
  156. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +146 -682
  157. package/dist/icons/spinner-solid-neutral-icon/index.tsx +1 -1
  158. package/dist/icons/star-icon/StarIcon.stories.tsx +124 -904
  159. package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +112 -964
  160. package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +116 -852
  161. package/dist/icons/sun-icon/SunIcon.stories.tsx +120 -831
  162. package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +116 -950
  163. package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +123 -980
  164. package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +156 -1427
  165. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +146 -1142
  166. package/dist/icons/tick-icon/TickIcon.stories.tsx +145 -1276
  167. package/dist/icons/trash-icon/TrashIcon.stories.tsx +108 -933
  168. package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +157 -1402
  169. package/dist/icons/upload-icon/UploadIcon.stories.tsx +115 -889
  170. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +118 -984
  171. package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +125 -1049
  172. package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +123 -1356
  173. package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +110 -1171
  174. package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +112 -1093
  175. package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +115 -1087
  176. package/dist/icons/warning-icon/WarningIcon.stories.tsx +122 -1046
  177. package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +161 -936
  178. package/dist/index.cjs +84 -84
  179. package/dist/index.js +84 -84
  180. package/dist/styles/aural-all-theme.css +1222 -0
  181. package/dist/styles/{aural-theme.css → aural-dark-theme.css} +15 -3
  182. package/dist/styles/aural-light-theme.css +1047 -0
  183. package/package.json +1 -1
@@ -1,24 +1,22 @@
1
1
  import React from "react"
2
2
  import { Badge } from "@components/badge"
3
3
  import {
4
- BubbleCheckIcon,
5
- BubbleSparkleIcon,
6
- EditBigIcon,
7
- EyeOpenIcon,
8
4
  FeatureShineIcon,
9
- FileChartIcon,
10
- ImageIcon,
11
- ImportFolderIcon,
12
- LightBulbSimpleIcon,
13
- MagicBookIcon,
14
- MaintenanceIcon,
5
+ HeartIcon,
6
+ MusicalNoteIcon,
7
+ PauseIcon,
15
8
  SearchIcon,
16
- TickIcon,
9
+ SettingIcon,
10
+ SkipForwardIcon,
11
+ StarIcon,
17
12
  TrashIcon,
18
13
  UploadIcon,
14
+ VolumeFullIcon,
19
15
  } from "@icons/index"
20
16
  import type { Meta, StoryObj } from "@storybook/react-vite"
21
17
 
18
+ import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
19
+
22
20
  import {
23
21
  List,
24
22
  ListCheckboxItem,
@@ -35,114 +33,30 @@ const meta: Meta<typeof List> = {
35
33
  title: "Components/UI/List",
36
34
  component: List,
37
35
  parameters: {
38
- layout: "fullscreen",
39
- backgrounds: {
40
- default: "dark",
41
- values: [
42
- { name: "dark", value: "#0a0a0a" },
43
- { name: "light", value: "#ffffff" },
44
- ],
45
- },
36
+ layout: "centered",
46
37
  docs: {
47
38
  description: {
48
- component: `
49
- # List Component
50
-
51
- A comprehensive atomic list component system that provides building blocks for creating rich interactive lists, menus, and selection interfaces. Built following atomic design principles.
52
-
53
- ## Atomic Components
54
-
55
- ### Container Level
56
- - **List**: Main container with styling variants and border options
57
- - **ListGroup**: Semantic grouping wrapper for related list items
58
-
59
- ### Content Level
60
- - **ListItem**: Basic interactive list item with states and variants
61
- - **ListCheckboxItem**: Checkbox-enabled list item for multi-selection
62
- - **ListRadioItem**: Radio button list item for single selection within groups
63
- - **ListLabel**: Semantic label component for list sections
64
- - **ListSeparator**: Visual separator using design system divider
65
- - **ListSubTrigger**: List item with chevron for nested navigation
66
-
67
- ## Features
68
-
69
- - **Atomic Design**: Composable components following atomic design principles
70
- - **Flexible Styling**: CVA variants for size, state, and visual styling
71
- - **Interactive States**: Hover, focus, selected, and disabled states
72
- - **Selection Patterns**: Support for single, multi, and radio group selection
73
- - **Keyboard Navigation**: Full keyboard accessibility support
74
- - **Icon Integration**: Seamless icon support with proper sizing and coloring
75
- - **Shortcuts Display**: Built-in keyboard shortcut display
76
- - **Custom Styling**: Extensive customization through classes prop
77
- - **Semantic HTML**: Proper ARIA roles and attributes for accessibility
78
-
79
- ## Usage Examples
80
-
81
- ### Basic List
82
- \`\`\`tsx
83
- <List>
84
- <ListItem>
85
- <FileChartIcon />
86
- Basic Item
87
- </ListItem>
88
- <ListSeparator />
89
- <ListItem selected>
90
- <ImageIcon />
91
- Selected Item
92
- </ListItem>
93
- </List>
94
- \`\`\`
95
-
96
- ### Grouped List with Labels
97
- \`\`\`tsx
98
- <List>
99
- <ListGroup>
100
- <ListLabel>Actions</ListLabel>
101
- <ListItem>
102
- <EditBigIcon />
103
- Edit File
104
- <CommandShortcut>⌘E</CommandShortcut>
105
- </ListItem>
106
- <ListItem variant="destructive">
107
- <TrashIcon />
108
- Delete
109
- </ListItem>
110
- </ListGroup>
111
- </List>
112
- \`\`\`
113
-
114
- ### Selection Lists
115
- \`\`\`tsx
116
- <List>
117
- <ListCheckboxItem checked onCheckedChange={setChecked}>
118
- Multi-select Item
119
- </ListCheckboxItem>
120
-
121
- <ListRadioGroup value={value} onValueChange={setValue}>
122
- <ListRadioItem value="option1">Option 1</ListRadioItem>
123
- <ListRadioItem value="option2">Option 2</ListRadioItem>
124
- </ListRadioGroup>
125
- </List>
126
- \`\`\`
127
-
128
- ### Custom Styling
129
- \`\`\`tsx
130
- <List
131
- variant="elevated"
132
- size="lg"
133
- borderVariant="success"
134
- classes={{ root: "custom-list" }}
135
- >
136
- <ListItem
137
- size="lg"
138
- classes={{ root: "custom-item" }}
139
- >
140
- Custom Styled Item
141
- </ListItem>
142
- </List>
143
- \`\`\`
144
- `,
39
+ component:
40
+ "A compound list system built for composable menus, selection panels, and navigation drawers. Composed of List (container), ListGroup, ListLabel, ListItem, ListCheckboxItem, ListRadioGroup, ListRadioItem, ListSeparator, and ListSubTrigger. Supports three visual variants (default, elevated, flat), four container sizes (sm, default, lg, xl), and semantic top-border accents.",
145
41
  },
42
+ page: () => (
43
+ <AuralComponentDocsPage
44
+ features={[
45
+ {
46
+ title: "Rich Item Types",
47
+ description: "Checkbox, radio, sub-trigger",
48
+ },
49
+ {
50
+ title: "3 Variants",
51
+ description: "Default, elevated, flat",
52
+ },
53
+ {
54
+ title: "4 Container Sizes",
55
+ description: "sm to xl width",
56
+ },
57
+ ]}
58
+ />
59
+ ),
146
60
  },
147
61
  },
148
62
  tags: ["autodocs"],
@@ -150,26 +64,26 @@ A comprehensive atomic list component system that provides building blocks for c
150
64
  variant: {
151
65
  control: "select",
152
66
  options: ["default", "elevated", "flat"],
153
- description: "Visual style variant of the list container",
67
+ description: "Visual shadow depth of the list container",
154
68
  },
155
69
  size: {
156
70
  control: "select",
157
71
  options: ["sm", "default", "lg", "xl"],
158
- description: "Size variant affecting minimum width",
72
+ description: "Minimum width of the list container",
159
73
  },
160
74
  rounded: {
161
75
  control: "select",
162
76
  options: ["none", "sm", "default", "lg"],
163
- description: "Border radius variant",
77
+ description: "Border radius of the list container",
164
78
  },
165
79
  borderVariant: {
166
80
  control: "select",
167
81
  options: ["default", "error", "warning", "success", "info"],
168
- description: "Color variant for the top border accent",
82
+ description: "Color of the top accent border stripe",
169
83
  },
170
84
  showBorder: {
171
85
  control: "boolean",
172
- description: "Whether to show the top accent border",
86
+ description: "Toggle the top accent border stripe",
173
87
  },
174
88
  },
175
89
  }
@@ -177,775 +91,523 @@ A comprehensive atomic list component system that provides building blocks for c
177
91
  export default meta
178
92
  type Story = StoryObj<typeof List>
179
93
 
180
- // 1. Basic List
181
- export const BasicList: Story = {
182
- args: {
183
- variant: "default",
184
- size: "default",
185
- rounded: "default",
186
- borderVariant: "default",
187
- showBorder: true,
188
- },
189
- render: (args) => (
190
- <div className="mx-auto max-w-md p-8">
191
- <h3 className="mb-4 text-lg font-medium text-white">Basic List</h3>
192
- <List {...args} className="backdrop-blur-none">
193
- <ListItem>
194
- <FileChartIcon />
195
- Documents
196
- </ListItem>
197
- <ListItem>
198
- <ImageIcon />
199
- Images
200
- </ListItem>
201
- <ListItem selected>
202
- <MagicBookIcon />
203
- Magic Book (Selected)
204
- </ListItem>
205
- <ListItem disabled>
206
- <TrashIcon />
207
- Disabled Item
208
- </ListItem>
209
- </List>
210
- </div>
211
- ),
212
- parameters: {
213
- docs: {
214
- description: {
215
- story:
216
- "Basic list with icons and different states including selected and disabled items.",
217
- },
218
- },
219
- },
220
- }
94
+ // ─── 1. Parts ─────────────────────────────────────────────────────────────────
221
95
 
222
- // 2. List with Groups and Labels
223
- export const GroupedList: Story = {
96
+ export const Parts: Story = {
224
97
  render: () => (
225
- <div className="mx-auto max-w-md p-8">
226
- <h3 className="mb-4 text-lg font-medium text-white">
227
- Grouped List with Labels
228
- </h3>
229
- <List>
230
- <ListGroup>
231
- <ListLabel>File Operations</ListLabel>
232
- <ListItem>
233
- <FileChartIcon />
234
- New Document
235
- <span className="ml-auto text-xs opacity-60">⌘N</span>
236
- </ListItem>
98
+ <div className="mx-auto w-full max-w-2xl space-y-10">
99
+ {/* List (container) */}
100
+ <div className="space-y-4">
101
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
102
+ List — container
103
+ </h4>
104
+ <List className="w-56">
105
+ <ListItem>Sample item A</ListItem>
106
+ <ListItem>Sample item B</ListItem>
107
+ </List>
108
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
109
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
110
+ <strong className="text-fm-primary">List</strong> is the root
111
+ container. It applies a frosted-glass backdrop, shadow, and optional
112
+ top-accent border. Sets <code>role="listbox"</code> for
113
+ accessibility.
114
+ </p>
115
+ </div>
116
+ </div>
117
+
118
+ {/* ListGroup */}
119
+ <div className="space-y-4">
120
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
121
+ ListGroup — semantic grouping
122
+ </h4>
123
+ <List className="w-56">
124
+ <ListGroup>
125
+ <ListItem>Group A · Item 1</ListItem>
126
+ <ListItem>Group A · Item 2</ListItem>
127
+ </ListGroup>
128
+ <ListSeparator />
129
+ <ListGroup>
130
+ <ListItem>Group B · Item 1</ListItem>
131
+ </ListGroup>
132
+ </List>
133
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
134
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
135
+ <strong className="text-fm-primary">ListGroup</strong> wraps related
136
+ items with <code>role="group"</code>. Use it alongside{" "}
137
+ <code>ListSeparator</code> to divide the list into semantic
138
+ sections.
139
+ </p>
140
+ </div>
141
+ </div>
142
+
143
+ {/* ListLabel */}
144
+ <div className="space-y-4">
145
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
146
+ ListLabel — section heading
147
+ </h4>
148
+ <List className="w-56">
149
+ <ListLabel>Playback</ListLabel>
237
150
  <ListItem>
238
- <ImportFolderIcon />
239
- Open Folder
240
- <span className="ml-auto text-xs opacity-60">⌘O</span>
151
+ <PauseIcon className="size-4" />
152
+ Pause
241
153
  </ListItem>
242
154
  <ListItem>
243
- <EditBigIcon />
244
- Edit File
245
- <span className="ml-auto text-xs opacity-60">⌘E</span>
155
+ <SkipForwardIcon className="size-4" />
156
+ Skip
246
157
  </ListItem>
247
- </ListGroup>
248
-
249
- <ListSeparator />
158
+ </List>
159
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
160
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
161
+ <strong className="text-fm-primary">ListLabel</strong> renders a
162
+ small, muted uppercase heading above a group of items. It uses{" "}
163
+ <code>text-fm-label-secondary</code> — not interactive.
164
+ </p>
165
+ </div>
166
+ </div>
250
167
 
251
- <ListGroup>
252
- <ListLabel>Actions</ListLabel>
168
+ {/* ListItem */}
169
+ <div className="space-y-4">
170
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
171
+ ListItem — basic row
172
+ </h4>
173
+ <List className="w-56">
253
174
  <ListItem>
254
- <BubbleSparkleIcon />
255
- Share
256
- <Badge color="info" className="ml-auto">
257
- New
258
- </Badge>
175
+ <MusicalNoteIcon className="size-4" />
176
+ Default
259
177
  </ListItem>
260
- <ListItem>
261
- <UploadIcon />
262
- Upload
178
+ <ListItem selected>
179
+ <StarIcon className="size-4" />
180
+ Selected
181
+ </ListItem>
182
+ <ListItem disabled>
183
+ <TrashIcon className="size-4" />
184
+ Disabled
263
185
  </ListItem>
264
- <ListSubTrigger>
265
- <MaintenanceIcon />
266
- More Options
267
- </ListSubTrigger>
268
- </ListGroup>
269
-
270
- <ListSeparator />
271
-
272
- <ListGroup>
273
- <ListLabel>Dangerous Actions</ListLabel>
274
186
  <ListItem variant="destructive">
275
- <TrashIcon />
276
- Delete
277
- <span className="ml-auto text-xs opacity-60">⌘⌫</span>
187
+ <TrashIcon className="size-4" />
188
+ Destructive
278
189
  </ListItem>
279
- </ListGroup>
280
- </List>
281
- </div>
282
- ),
283
- parameters: {
284
- docs: {
285
- description: {
286
- story:
287
- "Organized list with groups, labels, separators, shortcuts, badges, and a sub-trigger for nested navigation.",
288
- },
289
- },
290
- },
291
- }
292
-
293
- // 3. Selection Lists
294
- export const SelectionLists: Story = {
295
- render: () => {
296
- const [checkedItems, setCheckedItems] = React.useState<string[]>([
297
- "item1",
298
- "item3",
299
- ])
300
- const [radioValue, setRadioValue] = React.useState("option2")
301
-
302
- const handleCheckboxChange = (itemId: string, checked: boolean) => {
303
- setCheckedItems((prev) =>
304
- checked ? [...prev, itemId] : prev.filter((id) => id !== itemId)
305
- )
306
- }
307
-
308
- return (
309
- <div className="space-y-8 p-8">
310
- <h3 className="text-center text-lg font-medium text-white">
311
- Selection Lists
312
- </h3>
313
-
314
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
315
- {/* Checkbox List */}
316
- <div className="space-y-4">
317
- <h4 className="text-sm font-medium text-white/70">
318
- Multi-Select (Checkbox)
319
- </h4>
320
- <List size="default">
321
- <ListLabel>Choose Features</ListLabel>
322
- <ListCheckboxItem
323
- checked={checkedItems.includes("item1")}
324
- onCheckedChange={(checked) =>
325
- handleCheckboxChange("item1", checked)
326
- }
327
- >
328
- <FeatureShineIcon />
329
- Advanced Analytics
330
- </ListCheckboxItem>
331
- <ListCheckboxItem
332
- checked={checkedItems.includes("item2")}
333
- onCheckedChange={(checked) =>
334
- handleCheckboxChange("item2", checked)
335
- }
336
- >
337
- <BubbleSparkleIcon />
338
- Real-time Sync
339
- </ListCheckboxItem>
340
- <ListCheckboxItem
341
- checked={checkedItems.includes("item3")}
342
- onCheckedChange={(checked) =>
343
- handleCheckboxChange("item3", checked)
344
- }
345
- >
346
- <LightBulbSimpleIcon />
347
- AI Suggestions
348
- </ListCheckboxItem>
349
- <ListCheckboxItem
350
- disabled
351
- checked={checkedItems.includes("item4")}
352
- onCheckedChange={(checked) =>
353
- handleCheckboxChange("item4", checked)
354
- }
355
- >
356
- <MaintenanceIcon />
357
- Premium Feature (Disabled)
358
- </ListCheckboxItem>
359
- </List>
360
-
361
- {checkedItems.length > 0 && (
362
- <div className="rounded-lg border border-white/10 bg-white/5 p-3">
363
- <p className="text-xs text-white/60">
364
- Selected: {checkedItems.length} feature
365
- {checkedItems.length !== 1 ? "s" : ""}
366
- </p>
367
- </div>
368
- )}
369
- </div>
370
-
371
- {/* Radio List */}
372
- <div className="space-y-4">
373
- <h4 className="text-sm font-medium text-white/70">
374
- Single Select (Radio)
375
- </h4>
376
- <List size="default">
377
- <ListLabel>Choose Theme</ListLabel>
378
- <ListRadioGroup value={radioValue} onValueChange={setRadioValue}>
379
- <ListRadioItem value="option1">
380
- <EyeOpenIcon />
381
- Light Theme
382
- </ListRadioItem>
383
- <ListRadioItem value="option2">
384
- <MaintenanceIcon />
385
- Dark Theme
386
- </ListRadioItem>
387
- <ListRadioItem value="option3">
388
- <FeatureShineIcon />
389
- Auto Theme
390
- </ListRadioItem>
391
- <ListRadioItem value="option4" disabled>
392
- <BubbleSparkleIcon />
393
- Custom Theme (Pro)
394
- </ListRadioItem>
395
- </ListRadioGroup>
396
- </List>
397
-
398
- <div className="rounded-lg border border-white/10 bg-white/5 p-3">
399
- <p className="text-xs text-white/60">
400
- Selected:{" "}
401
- {radioValue === "option1"
402
- ? "Light Theme"
403
- : radioValue === "option2"
404
- ? "Dark Theme"
405
- : radioValue === "option3"
406
- ? "Auto Theme"
407
- : "Custom Theme"}
408
- </p>
409
- </div>
410
- </div>
190
+ </List>
191
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
192
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
193
+ <strong className="text-fm-primary">ListItem</strong> is the primary
194
+ interactive row. Supports <code>selected</code>,{" "}
195
+ <code>disabled</code>, and <code>variant="destructive"</code>{" "}
196
+ states, plus an optional right-aligned keyboard shortcut via the{" "}
197
+ <code>shortcut</code> prop.
198
+ </p>
411
199
  </div>
412
200
  </div>
413
- )
414
- },
415
- parameters: {
416
- docs: {
417
- description: {
418
- story:
419
- "Interactive selection lists showing checkbox multi-select and radio single-select patterns with state management.",
420
- },
421
- },
422
- },
423
- }
424
-
425
- // 4. List Variants
426
- export const ListVariants: Story = {
427
- render: () => (
428
- <div className="space-y-8 p-8">
429
- <h3 className="text-center text-lg font-medium text-white">
430
- List Variants
431
- </h3>
432
-
433
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
434
- {/* Default Variant */}
435
- <div className="space-y-4">
436
- <h4 className="text-sm font-medium text-white/70">Default</h4>
437
- <List variant="default" size="default">
438
- <ListItem>
439
- <FileChartIcon />
440
- Default Style
441
- </ListItem>
442
- <ListItem selected>
443
- <ImageIcon />
444
- Selected Item
445
- </ListItem>
446
- <ListItem>
447
- <MagicBookIcon />
448
- Regular Item
449
- </ListItem>
450
- </List>
451
- </div>
452
-
453
- {/* Elevated Variant */}
454
- <div className="space-y-4">
455
- <h4 className="text-sm font-medium text-white/70">Elevated</h4>
456
- <List variant="elevated" size="default">
457
- <ListItem>
458
- <FeatureShineIcon />
459
- Elevated Style
460
- </ListItem>
461
- <ListItem selected>
462
- <BubbleSparkleIcon />
463
- More Shadow
464
- </ListItem>
465
- <ListItem>
466
- <LightBulbSimpleIcon />
467
- Premium Feel
468
- </ListItem>
469
- </List>
470
- </div>
471
201
 
472
- {/* Flat Variant */}
473
- <div className="space-y-4">
474
- <h4 className="text-sm font-medium text-white/70">Flat</h4>
475
- <List variant="flat" size="default">
476
- <ListItem>
477
- <MaintenanceIcon />
478
- Flat Style
479
- </ListItem>
480
- <ListItem selected>
481
- <EyeOpenIcon />
482
- Minimal Shadow
483
- </ListItem>
484
- <ListItem>
485
- <SearchIcon />
486
- Clean Look
487
- </ListItem>
488
- </List>
202
+ {/* ListCheckboxItem */}
203
+ <div className="space-y-4">
204
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
205
+ ListCheckboxItem multi-select row
206
+ </h4>
207
+ <List className="w-56">
208
+ <ListCheckboxItem checked>
209
+ <FeatureShineIcon className="size-4" />
210
+ Spatial Audio
211
+ </ListCheckboxItem>
212
+ <ListCheckboxItem>
213
+ <VolumeFullIcon className="size-4" />
214
+ Crossfade
215
+ </ListCheckboxItem>
216
+ <ListCheckboxItem disabled>
217
+ <SettingIcon className="size-4" />
218
+ Equalizer (Pro)
219
+ </ListCheckboxItem>
220
+ </List>
221
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
222
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
223
+ <strong className="text-fm-primary">ListCheckboxItem</strong>{" "}
224
+ extends ListItem with a tick indicator on the right. Use{" "}
225
+ <code>checked</code> and <code>onCheckedChange</code> for controlled
226
+ state.
227
+ </p>
489
228
  </div>
490
229
  </div>
491
- </div>
492
- ),
493
- parameters: {
494
- docs: {
495
- description: {
496
- story:
497
- "Different visual variants of the list component: default, elevated (more shadow), and flat (minimal shadow).",
498
- },
499
- },
500
- },
501
- }
502
-
503
- // 5. List Sizes
504
- export const ListSizes: Story = {
505
- render: () => (
506
- <div className="space-y-8 p-8">
507
- <h3 className="text-center text-lg font-medium text-white">List Sizes</h3>
508
-
509
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-4">
510
- {/* Small */}
511
- <div className="space-y-4">
512
- <h4 className="text-sm font-medium text-white/70">Small</h4>
513
- <List size="sm">
514
- <ListItem size="sm">
515
- <FileChartIcon />
516
- Small Item
517
- </ListItem>
518
- <ListItem size="sm" selected>
519
- <ImageIcon />
520
- Selected
521
- </ListItem>
522
- </List>
523
- </div>
524
230
 
525
- {/* Default */}
526
- <div className="space-y-4">
527
- <h4 className="text-sm font-medium text-white/70">Default</h4>
528
- <List size="default">
529
- <ListItem size="default">
530
- <MagicBookIcon />
531
- Default Item
532
- </ListItem>
533
- <ListItem size="default" selected>
534
- <FeatureShineIcon />
535
- Selected
536
- </ListItem>
537
- </List>
538
- </div>
539
-
540
- {/* Large */}
541
- <div className="space-y-4">
542
- <h4 className="text-sm font-medium text-white/70">Large</h4>
543
- <List size="lg">
544
- <ListItem size="lg">
545
- <BubbleSparkleIcon />
546
- Large Item
547
- </ListItem>
548
- <ListItem size="lg" selected>
549
- <LightBulbSimpleIcon />
550
- Selected
551
- </ListItem>
552
- </List>
553
- </div>
554
-
555
- {/* Extra Large */}
556
- <div className="space-y-4">
557
- <h4 className="text-sm font-medium text-white/70">Extra Large</h4>
558
- <List size="xl">
559
- <ListItem size="lg">
560
- <MaintenanceIcon />
561
- XL Container
562
- </ListItem>
563
- <ListItem size="lg" selected>
564
- <EyeOpenIcon />
565
- Large Items
566
- </ListItem>
567
- </List>
231
+ {/* ListRadioItem */}
232
+ <div className="space-y-4">
233
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
234
+ ListRadioItem — single-select row
235
+ </h4>
236
+ <List className="w-56">
237
+ <ListRadioGroup value="high">
238
+ <ListRadioItem value="low">Low Quality</ListRadioItem>
239
+ <ListRadioItem value="normal">Normal Quality</ListRadioItem>
240
+ <ListRadioItem value="high">High Quality</ListRadioItem>
241
+ </ListRadioGroup>
242
+ </List>
243
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
244
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
245
+ <strong className="text-fm-primary">ListRadioItem</strong> must be
246
+ nested inside a <code>ListRadioGroup</code>. The group manages the{" "}
247
+ <code>value</code>/<code>onValueChange</code> context so only one
248
+ item is selected at a time. Sets <code>role="radio"</code>.
249
+ </p>
568
250
  </div>
569
251
  </div>
570
- </div>
571
- ),
572
- parameters: {
573
- docs: {
574
- description: {
575
- story:
576
- "Different size variants affecting the minimum width of list containers and padding of list items.",
577
- },
578
- },
579
- },
580
- }
581
-
582
- // 6. Border Variants
583
- export const BorderVariants: Story = {
584
- render: () => (
585
- <div className="space-y-8 p-8">
586
- <h3 className="text-center text-lg font-medium text-white">
587
- Border Variants
588
- </h3>
589
-
590
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3 xl:grid-cols-5">
591
- {/* Default */}
592
- <div className="space-y-4">
593
- <h4 className="text-sm font-medium text-white/70">Default</h4>
594
- <List borderVariant="default">
595
- <ListItem>
596
- <FileChartIcon />
597
- Neutral
598
- </ListItem>
599
- <ListItem>
600
- <ImageIcon />
601
- Border
602
- </ListItem>
603
- </List>
604
- </div>
605
-
606
- {/* Success */}
607
- <div className="space-y-4">
608
- <h4 className="text-sm font-medium text-white/70">Success</h4>
609
- <List borderVariant="success">
610
- <ListItem>
611
- <BubbleCheckIcon />
612
- Success
613
- </ListItem>
614
- <ListItem>
615
- <TickIcon />
616
- Complete
617
- </ListItem>
618
- </List>
619
- </div>
620
-
621
- {/* Error */}
622
- <div className="space-y-4">
623
- <h4 className="text-sm font-medium text-white/70">Error</h4>
624
- <List borderVariant="error">
625
- <ListItem>
626
- <TrashIcon />
627
- Error
628
- </ListItem>
629
- <ListItem>
630
- <MaintenanceIcon />
631
- Issues
632
- </ListItem>
633
- </List>
634
- </div>
635
-
636
- {/* Warning */}
637
- <div className="space-y-4">
638
- <h4 className="text-sm font-medium text-white/70">Warning</h4>
639
- <List borderVariant="warning">
640
- <ListItem>
641
- <LightBulbSimpleIcon />
642
- Warning
643
- </ListItem>
644
- <ListItem>
645
- <MaintenanceIcon />
646
- Caution
647
- </ListItem>
648
- </List>
649
- </div>
650
252
 
651
- {/* Info */}
652
- <div className="space-y-4">
653
- <h4 className="text-sm font-medium text-white/70">Info</h4>
654
- <List borderVariant="info">
655
- <ListItem>
656
- <FeatureShineIcon />
657
- Info
658
- </ListItem>
659
- <ListItem>
660
- <BubbleSparkleIcon />
661
- Details
662
- </ListItem>
663
- </List>
253
+ {/* ListSeparator */}
254
+ <div className="space-y-4">
255
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
256
+ ListSeparator — visual divider
257
+ </h4>
258
+ <List className="w-56">
259
+ <ListItem>Above separator</ListItem>
260
+ <ListSeparator />
261
+ <ListItem>Below separator</ListItem>
262
+ </List>
263
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
264
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
265
+ <strong className="text-fm-primary">ListSeparator</strong> renders a
266
+ dashed divider using the design system <code>Divider</code>{" "}
267
+ component with <code>role="separator"</code>.
268
+ </p>
664
269
  </div>
665
270
  </div>
666
271
 
667
- {/* No Border */}
668
- <div className="mx-auto max-w-md">
669
- <h4 className="mb-4 text-sm font-medium text-white/70">No Border</h4>
670
- <List showBorder={false}>
671
- <ListItem>
672
- <SearchIcon />
673
- No top border
674
- </ListItem>
272
+ {/* ListSubTrigger */}
273
+ <div className="space-y-4">
274
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
275
+ ListSubTrigger — nested navigation
276
+ </h4>
277
+ <List className="w-56">
675
278
  <ListItem>
676
- <EyeOpenIcon />
677
- Clean look
279
+ <SearchIcon className="size-4" />
280
+ Search
678
281
  </ListItem>
282
+ <ListSubTrigger>
283
+ <SettingIcon className="size-4" />
284
+ More Options
285
+ </ListSubTrigger>
679
286
  </List>
287
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
288
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
289
+ <strong className="text-fm-primary">ListSubTrigger</strong> is a
290
+ ListItem with a right-aligned chevron icon indicating a nested
291
+ sub-menu or flyout panel.
292
+ </p>
293
+ </div>
680
294
  </div>
681
295
  </div>
682
296
  ),
683
297
  parameters: {
298
+ layout: "padded",
684
299
  docs: {
685
300
  description: {
686
301
  story:
687
- "Different border color variants for semantic meaning and option to hide the border entirely.",
302
+ "Each sub-component of the List compound shown individually with a role explanation. Use this as a reference when composing list-based menus and selection panels.",
688
303
  },
689
304
  },
690
305
  },
691
306
  }
692
307
 
693
- // 7. Custom Styling
694
- export const CustomStyling: Story = {
308
+ // ─── 2. AllVariants ───────────────────────────────────────────────────────────
309
+
310
+ export const AllVariants: Story = {
695
311
  render: () => (
696
- <div className="space-y-8 p-8">
697
- <h3 className="text-center text-lg font-medium text-white">
698
- Custom Styling
699
- </h3>
312
+ <div className="space-y-8">
313
+ {/* Variant axis */}
314
+ <div className="space-y-4">
315
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
316
+ Variant
317
+ </h4>
318
+ <div className="flex flex-wrap items-start justify-center gap-6">
319
+ {(["default", "elevated", "flat"] as const).map((variant) => (
320
+ <div key={variant} className="space-y-2 text-center">
321
+ <List variant={variant} className="w-44">
322
+ <ListItem>
323
+ <MusicalNoteIcon className="size-4" />
324
+ Track item
325
+ </ListItem>
326
+ <ListItem selected>
327
+ <StarIcon className="size-4" />
328
+ Selected
329
+ </ListItem>
330
+ <ListItem>
331
+ <HeartIcon className="size-4" />
332
+ Liked
333
+ </ListItem>
334
+ </List>
335
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm capitalize">
336
+ {variant}
337
+ </p>
338
+ </div>
339
+ ))}
340
+ </div>
341
+ </div>
700
342
 
701
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
702
- {/* Custom Classes */}
703
- <div className="space-y-4">
704
- <h4 className="text-sm font-medium text-white/70">Custom Classes</h4>
705
- <List
706
- className="border-purple-500/30 bg-purple-900/10"
707
- classes={{
708
- root: "backdrop-blur-xl",
709
- border: "bg-gradient-to-r from-purple-500 to-pink-500",
710
- }}
711
- borderVariant="info"
712
- >
713
- <ListItem
714
- classes={{
715
- root: "hover:bg-purple-500/20 text-purple-100",
716
- }}
717
- >
718
- <FeatureShineIcon />
719
- Purple Theme
720
- </ListItem>
721
- <ListItem
722
- selected
723
- classes={{
724
- root: "bg-purple-500/30 text-white",
725
- }}
726
- >
727
- <BubbleSparkleIcon />
728
- Custom Selected
729
- </ListItem>
730
- <ListItem
731
- classes={{
732
- root: "hover:bg-purple-500/20 text-purple-100",
733
- }}
734
- >
735
- <MagicBookIcon />
736
- Magic Item
737
- </ListItem>
738
- </List>
343
+ {/* Size axis */}
344
+ <div className="space-y-4">
345
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
346
+ Size
347
+ </h4>
348
+ <div className="flex flex-wrap items-start justify-center gap-6">
349
+ {(["sm", "default", "lg", "xl"] as const).map((size) => (
350
+ <div key={size} className="space-y-2 text-center">
351
+ <List size={size}>
352
+ <ListItem size={size === "xl" ? "lg" : size}>
353
+ <MusicalNoteIcon className="size-4" />
354
+ Item
355
+ </ListItem>
356
+ <ListItem size={size === "xl" ? "lg" : size} selected>
357
+ <StarIcon className="size-4" />
358
+ Selected
359
+ </ListItem>
360
+ </List>
361
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
362
+ {size}
363
+ </p>
364
+ </div>
365
+ ))}
739
366
  </div>
367
+ </div>
740
368
 
741
- {/* Complex Layout */}
742
- <div className="space-y-4">
743
- <h4 className="text-sm font-medium text-white/70">Complex Layout</h4>
744
- <List variant="elevated" size="lg">
745
- <ListLabel size="lg">Premium Features</ListLabel>
746
- <ListItem size="lg">
747
- <div className="flex items-center gap-3">
748
- <div className="rounded-full bg-green-500/20 p-2">
749
- <TickIcon className="size-4 text-green-400" />
750
- </div>
751
- <div className="flex-1">
752
- <div className="font-medium text-white">
753
- Advanced Analytics
754
- </div>
755
- <div className="text-xs text-white/60">
756
- Deep insights and reporting
757
- </div>
758
- </div>
759
- <Badge color="positive">Active</Badge>
760
- </div>
761
- </ListItem>
762
- <ListItem size="lg">
763
- <div className="flex items-center gap-3">
764
- <div className="rounded-full bg-blue-500/20 p-2">
765
- <FeatureShineIcon className="size-4 text-blue-400" />
766
- </div>
767
- <div className="flex-1">
768
- <div className="font-medium text-white">AI Assistant</div>
769
- <div className="text-xs text-white/60">
770
- Intelligent automation
771
- </div>
772
- </div>
773
- <Badge color="info">Beta</Badge>
369
+ {/* Border variant axis */}
370
+ <div className="space-y-4">
371
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
372
+ Border Variant
373
+ </h4>
374
+ <div className="flex flex-wrap items-start justify-center gap-6">
375
+ {(["default", "success", "error", "warning", "info"] as const).map(
376
+ (bv) => (
377
+ <div key={bv} className="space-y-2 text-center">
378
+ <List borderVariant={bv} className="w-36">
379
+ <ListItem>Item A</ListItem>
380
+ <ListItem>Item B</ListItem>
381
+ </List>
382
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm capitalize">
383
+ {bv}
384
+ </p>
774
385
  </div>
775
- </ListItem>
776
- <ListItem size="lg" disabled>
777
- <div className="flex items-center gap-3">
778
- <div className="rounded-full bg-gray-500/20 p-2">
779
- <LightBulbSimpleIcon className="size-4 text-gray-400" />
780
- </div>
781
- <div className="flex-1">
782
- <div className="font-medium">Custom Workflows</div>
783
- <div className="text-xs text-white/40">Coming soon</div>
784
- </div>
785
- <Badge color="neutral">Soon</Badge>
386
+ )
387
+ )}
388
+ <div className="space-y-2 text-center">
389
+ <List showBorder={false} className="w-36">
390
+ <ListItem>Item A</ListItem>
391
+ <ListItem>Item B</ListItem>
392
+ </List>
393
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
394
+ No border
395
+ </p>
396
+ </div>
397
+ </div>
398
+ </div>
399
+
400
+ {/* Variant × size matrix */}
401
+ <div className="space-y-4">
402
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
403
+ Variant × Size matrix
404
+ </h4>
405
+ <div className="mx-auto grid max-w-4xl grid-cols-2 gap-6 sm:grid-cols-3 lg:grid-cols-4">
406
+ {(["default", "elevated", "flat"] as const).flatMap((variant) =>
407
+ (["sm", "default", "lg"] as const).map((size) => (
408
+ <div key={`${variant}-${size}`} className="space-y-2 text-center">
409
+ <List variant={variant} size={size}>
410
+ <ListItem size={size}>
411
+ <MusicalNoteIcon className="size-4" />
412
+ Track
413
+ </ListItem>
414
+ <ListItem size={size} selected>
415
+ <StarIcon className="size-4" />
416
+ Active
417
+ </ListItem>
418
+ </List>
419
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
420
+ {variant} · {size}
421
+ </p>
786
422
  </div>
787
- </ListItem>
788
- </List>
423
+ ))
424
+ )}
789
425
  </div>
790
426
  </div>
791
427
  </div>
792
428
  ),
793
429
  parameters: {
430
+ layout: "padded",
794
431
  docs: {
795
432
  description: {
796
433
  story:
797
- "Examples of custom styling using classes prop and complex layouts with rich content, badges, and custom color schemes.",
434
+ "Full visual matrix across variants (default, elevated, flat), sizes (sm, default, lg, xl), border variants, and a variant × size cross-axis comparison.",
798
435
  },
799
436
  },
800
437
  },
801
438
  }
802
439
 
803
- // 8. Interactive Showcase
804
- export const InteractiveShowcase: Story = {
440
+ // ─── 3. Interactive ───────────────────────────────────────────────────────────
441
+
442
+ export const Interactive: Story = {
805
443
  render: () => {
806
- const [selectedItems, setSelectedItems] = React.useState<string[]>([
807
- "item2",
808
- ])
809
- const [checkedFeatures, setCheckedFeatures] = React.useState<string[]>([
810
- "analytics",
444
+ const [enabledFeatures, setEnabledFeatures] = React.useState<string[]>([
445
+ "spatial",
446
+ "crossfade",
811
447
  ])
812
- const [theme, setTheme] = React.useState("dark")
448
+ const [audioQuality, setAudioQuality] = React.useState("high")
449
+ const [activeTab, setActiveTab] = React.useState("tracks")
813
450
 
814
- const handleItemSelect = (itemId: string) => {
815
- setSelectedItems([itemId])
451
+ const toggleFeature = (id: string, checked: boolean) => {
452
+ setEnabledFeatures((prev) =>
453
+ checked ? [...prev, id] : prev.filter((f) => f !== id)
454
+ )
816
455
  }
817
456
 
818
- const handleFeatureToggle = (featureId: string, checked: boolean) => {
819
- setCheckedFeatures((prev) =>
820
- checked ? [...prev, featureId] : prev.filter((id) => id !== featureId)
821
- )
457
+ const qualityLabel: Record<string, string> = {
458
+ low: "Low (96 kbps)",
459
+ normal: "Normal (160 kbps)",
460
+ high: "High (320 kbps)",
461
+ lossless: "Lossless (FLAC)",
822
462
  }
823
463
 
824
464
  return (
825
- <div className="space-y-8 p-8">
826
- <h3 className="text-center text-lg font-medium text-white">
827
- Interactive Showcase
828
- </h3>
829
-
830
- <div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
831
- {/* Navigation List */}
832
- <div className="space-y-4">
833
- <h4 className="text-sm font-medium text-white/70">Navigation</h4>
834
- <List>
835
- <ListLabel>Main Menu</ListLabel>
836
- <ListItem
837
- selected={selectedItems.includes("item1")}
838
- onClick={() => handleItemSelect("item1")}
839
- className="cursor-pointer"
840
- >
841
- <FileChartIcon />
842
- Dashboard
843
- </ListItem>
844
- <ListItem
845
- selected={selectedItems.includes("item2")}
846
- onClick={() => handleItemSelect("item2")}
847
- className="cursor-pointer"
848
- >
849
- <ImageIcon />
850
- Media Library
851
- <Badge color="info" className="ml-auto">
852
- 12
853
- </Badge>
854
- </ListItem>
855
- <ListItem
856
- selected={selectedItems.includes("item3")}
857
- onClick={() => handleItemSelect("item3")}
858
- className="cursor-pointer"
859
- >
860
- <MaintenanceIcon />
861
- Settings
862
- </ListItem>
863
- <ListSeparator />
864
- <ListSubTrigger>
865
- <BubbleSparkleIcon />
866
- Advanced Options
867
- </ListSubTrigger>
868
- </List>
869
- </div>
465
+ <div className="w-full p-8">
466
+ <div className="mx-auto w-full max-w-4xl space-y-6">
467
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
468
+ {/* Controls panel */}
469
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
470
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
471
+ Navigation
472
+ </p>
473
+ <List showBorder={false} className="w-full">
474
+ <ListItem
475
+ selected={activeTab === "tracks"}
476
+ className="cursor-pointer"
477
+ onClick={() => setActiveTab("tracks")}
478
+ >
479
+ <MusicalNoteIcon className="size-4" />
480
+ Tracks
481
+ </ListItem>
482
+ <ListItem
483
+ selected={activeTab === "artists"}
484
+ className="cursor-pointer"
485
+ onClick={() => setActiveTab("artists")}
486
+ >
487
+ <StarIcon className="size-4" />
488
+ Artists
489
+ <Badge
490
+ color="info"
491
+ size="xs"
492
+ className="bg-fm-surface-info-sec text-fm-info-sec ml-auto"
493
+ >
494
+ NEW
495
+ </Badge>
496
+ </ListItem>
497
+ <ListItem
498
+ selected={activeTab === "liked"}
499
+ className="cursor-pointer"
500
+ onClick={() => setActiveTab("liked")}
501
+ >
502
+ <HeartIcon className="size-4" />
503
+ Liked Songs
504
+ </ListItem>
505
+ <ListItem
506
+ selected={activeTab === "uploads"}
507
+ className="cursor-pointer"
508
+ onClick={() => setActiveTab("uploads")}
509
+ >
510
+ <UploadIcon className="size-4" />
511
+ Uploads
512
+ </ListItem>
513
+ <ListSeparator />
514
+ <ListSubTrigger>
515
+ <SettingIcon className="size-4" />
516
+ Settings
517
+ </ListSubTrigger>
518
+ </List>
519
+ </div>
870
520
 
871
- {/* Feature Selection */}
872
- <div className="space-y-4">
873
- <h4 className="text-sm font-medium text-white/70">Features</h4>
874
- <List borderVariant="success">
875
- <ListLabel>Enable Features</ListLabel>
876
- <ListCheckboxItem
877
- checked={checkedFeatures.includes("analytics")}
878
- onCheckedChange={(checked) =>
879
- handleFeatureToggle("analytics", checked)
880
- }
881
- >
882
- <FeatureShineIcon />
883
- Analytics
884
- </ListCheckboxItem>
885
- <ListCheckboxItem
886
- checked={checkedFeatures.includes("ai")}
887
- onCheckedChange={(checked) =>
888
- handleFeatureToggle("ai", checked)
889
- }
890
- >
891
- <LightBulbSimpleIcon />
892
- AI Features
893
- </ListCheckboxItem>
894
- <ListCheckboxItem
895
- checked={checkedFeatures.includes("sync")}
896
- onCheckedChange={(checked) =>
897
- handleFeatureToggle("sync", checked)
898
- }
899
- >
900
- <BubbleSparkleIcon />
901
- Real-time Sync
902
- </ListCheckboxItem>
903
- </List>
904
- </div>
521
+ {/* Preview stage */}
522
+ <div className="flex flex-col gap-6 lg:col-span-2">
523
+ {/* Feature toggles */}
524
+ <div className="space-y-3">
525
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm font-medium">
526
+ Playback Features (multi-select)
527
+ </p>
528
+ <List borderVariant="success" className="w-full">
529
+ <ListLabel>Audio Enhancements</ListLabel>
530
+ <ListCheckboxItem
531
+ checked={enabledFeatures.includes("spatial")}
532
+ onCheckedChange={(c) => toggleFeature("spatial", c)}
533
+ >
534
+ <VolumeFullIcon className="size-4" />
535
+ Spatial Audio
536
+ </ListCheckboxItem>
537
+ <ListCheckboxItem
538
+ checked={enabledFeatures.includes("crossfade")}
539
+ onCheckedChange={(c) => toggleFeature("crossfade", c)}
540
+ >
541
+ <FeatureShineIcon className="size-4" />
542
+ Crossfade
543
+ </ListCheckboxItem>
544
+ <ListCheckboxItem
545
+ checked={enabledFeatures.includes("normalize")}
546
+ onCheckedChange={(c) => toggleFeature("normalize", c)}
547
+ >
548
+ <SettingIcon className="size-4" />
549
+ Volume Normalize
550
+ </ListCheckboxItem>
551
+ <ListCheckboxItem disabled>
552
+ <StarIcon className="size-4" />
553
+ Dolby Atmos (Pro)
554
+ </ListCheckboxItem>
555
+ </List>
556
+ </div>
905
557
 
906
- {/* Theme Selection */}
907
- <div className="space-y-4">
908
- <h4 className="text-sm font-medium text-white/70">Theme</h4>
909
- <List borderVariant="info">
910
- <ListLabel>Appearance</ListLabel>
911
- <ListRadioGroup value={theme}>
912
- <ListRadioItem value="light" onSelect={setTheme}>
913
- <EyeOpenIcon />
914
- Light Theme
915
- </ListRadioItem>
916
- <ListRadioItem value="dark" onSelect={setTheme}>
917
- <MaintenanceIcon />
918
- Dark Theme
919
- </ListRadioItem>
920
- <ListRadioItem value="auto" onSelect={setTheme}>
921
- <FeatureShineIcon />
922
- Auto Theme
923
- </ListRadioItem>
924
- </ListRadioGroup>
925
- </List>
926
- </div>
927
- </div>
558
+ {/* Quality selector */}
559
+ <div className="space-y-3">
560
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm font-medium">
561
+ Streaming Quality (single-select)
562
+ </p>
563
+ <List borderVariant="info" className="w-full">
564
+ <ListLabel>Audio Quality</ListLabel>
565
+ <ListRadioGroup
566
+ value={audioQuality}
567
+ onValueChange={setAudioQuality}
568
+ >
569
+ <ListRadioItem value="low">Low (96 kbps)</ListRadioItem>
570
+ <ListRadioItem value="normal">
571
+ Normal (160 kbps)
572
+ </ListRadioItem>
573
+ <ListRadioItem value="high">High (320 kbps)</ListRadioItem>
574
+ <ListRadioItem value="lossless">
575
+ Lossless (FLAC)
576
+ </ListRadioItem>
577
+ </ListRadioGroup>
578
+ </List>
579
+ </div>
928
580
 
929
- {/* Status Display */}
930
- <div className="mx-auto max-w-2xl rounded-lg border border-white/10 bg-white/5 p-4">
931
- <h4 className="mb-3 text-sm font-medium text-white">Current State</h4>
932
- <div className="grid grid-cols-1 gap-3 text-xs text-white/60 md:grid-cols-3">
933
- <div>
934
- <strong>Selected Page:</strong>{" "}
935
- {selectedItems.includes("item1")
936
- ? "Dashboard"
937
- : selectedItems.includes("item2")
938
- ? "Media Library"
939
- : selectedItems.includes("item3")
940
- ? "Settings"
941
- : "None"}
942
- </div>
943
- <div>
944
- <strong>Enabled Features:</strong>{" "}
945
- {checkedFeatures.length > 0 ? checkedFeatures.join(", ") : "None"}
946
- </div>
947
- <div>
948
- <strong>Theme:</strong> {theme}
581
+ {/* State readout */}
582
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
583
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold">
584
+ Current State
585
+ </p>
586
+ <div className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm grid grid-cols-1 gap-2 sm:grid-cols-3">
587
+ <div>
588
+ <span className="text-fm-primary font-medium">
589
+ Section:{" "}
590
+ </span>
591
+ <span className="capitalize">{activeTab}</span>
592
+ </div>
593
+ <div>
594
+ <span className="text-fm-primary font-medium">
595
+ Features:{" "}
596
+ </span>
597
+ <span>
598
+ {enabledFeatures.length > 0
599
+ ? enabledFeatures.join(", ")
600
+ : "none"}
601
+ </span>
602
+ </div>
603
+ <div>
604
+ <span className="text-fm-primary font-medium">
605
+ Quality:{" "}
606
+ </span>
607
+ <span>{qualityLabel[audioQuality]}</span>
608
+ </div>
609
+ </div>
610
+ </div>
949
611
  </div>
950
612
  </div>
951
613
  </div>
@@ -953,10 +615,11 @@ export const InteractiveShowcase: Story = {
953
615
  )
954
616
  },
955
617
  parameters: {
618
+ layout: "fullscreen",
956
619
  docs: {
957
620
  description: {
958
621
  story:
959
- "Fully interactive showcase demonstrating navigation selection, feature toggles, and theme selection with real-time state updates.",
622
+ "Fully interactive story demonstrating navigation selection (single active tab), multi-select feature toggles via ListCheckboxItem, and streaming quality selection via ListRadioItem — all with live state readout.",
960
623
  },
961
624
  },
962
625
  },