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,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,789 +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="text-fm-primary mb-4 text-lg font-medium">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="text-fm-primary mb-4 text-lg font-medium">
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-fm-primary text-center text-lg font-medium">
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-fm-secondary text-sm font-medium">
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="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
363
- <p className="text-fm-secondary text-xs">
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-fm-secondary text-sm font-medium">
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="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
399
- <p className="text-fm-secondary text-xs">
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-fm-primary text-center text-lg font-medium">
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-fm-secondary text-sm font-medium">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-fm-secondary text-sm font-medium">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-fm-secondary text-sm font-medium">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-fm-primary text-center text-lg font-medium">
508
- List Sizes
509
- </h3>
510
-
511
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-4">
512
- {/* Small */}
513
- <div className="space-y-4">
514
- <h4 className="text-fm-secondary text-sm font-medium">Small</h4>
515
- <List size="sm">
516
- <ListItem size="sm">
517
- <FileChartIcon />
518
- Small Item
519
- </ListItem>
520
- <ListItem size="sm" selected>
521
- <ImageIcon />
522
- Selected
523
- </ListItem>
524
- </List>
525
- </div>
526
-
527
- {/* Default */}
528
- <div className="space-y-4">
529
- <h4 className="text-fm-secondary text-sm font-medium">Default</h4>
530
- <List size="default">
531
- <ListItem size="default">
532
- <MagicBookIcon />
533
- Default Item
534
- </ListItem>
535
- <ListItem size="default" selected>
536
- <FeatureShineIcon />
537
- Selected
538
- </ListItem>
539
- </List>
540
- </div>
541
230
 
542
- {/* Large */}
543
- <div className="space-y-4">
544
- <h4 className="text-fm-secondary text-sm font-medium">Large</h4>
545
- <List size="lg">
546
- <ListItem size="lg">
547
- <BubbleSparkleIcon />
548
- Large Item
549
- </ListItem>
550
- <ListItem size="lg" selected>
551
- <LightBulbSimpleIcon />
552
- Selected
553
- </ListItem>
554
- </List>
555
- </div>
556
-
557
- {/* Extra Large */}
558
- <div className="space-y-4">
559
- <h4 className="text-fm-secondary text-sm font-medium">Extra Large</h4>
560
- <List size="xl">
561
- <ListItem size="lg">
562
- <MaintenanceIcon />
563
- XL Container
564
- </ListItem>
565
- <ListItem size="lg" selected>
566
- <EyeOpenIcon />
567
- Large Items
568
- </ListItem>
569
- </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>
570
250
  </div>
571
251
  </div>
572
- </div>
573
- ),
574
- parameters: {
575
- docs: {
576
- description: {
577
- story:
578
- "Different size variants affecting the minimum width of list containers and padding of list items.",
579
- },
580
- },
581
- },
582
- }
583
-
584
- // 6. Border Variants
585
- export const BorderVariants: Story = {
586
- render: () => (
587
- <div className="space-y-8 p-8">
588
- <h3 className="text-fm-primary text-center text-lg font-medium">
589
- Border Variants
590
- </h3>
591
-
592
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3 xl:grid-cols-5">
593
- {/* Default */}
594
- <div className="space-y-4">
595
- <h4 className="text-fm-secondary text-sm font-medium">Default</h4>
596
- <List borderVariant="default">
597
- <ListItem>
598
- <FileChartIcon />
599
- Neutral
600
- </ListItem>
601
- <ListItem>
602
- <ImageIcon />
603
- Border
604
- </ListItem>
605
- </List>
606
- </div>
607
-
608
- {/* Success */}
609
- <div className="space-y-4">
610
- <h4 className="text-fm-secondary text-sm font-medium">Success</h4>
611
- <List borderVariant="success">
612
- <ListItem>
613
- <BubbleCheckIcon />
614
- Success
615
- </ListItem>
616
- <ListItem>
617
- <TickIcon />
618
- Complete
619
- </ListItem>
620
- </List>
621
- </div>
622
252
 
623
- {/* Error */}
624
- <div className="space-y-4">
625
- <h4 className="text-fm-secondary text-sm font-medium">Error</h4>
626
- <List borderVariant="error">
627
- <ListItem>
628
- <TrashIcon />
629
- Error
630
- </ListItem>
631
- <ListItem>
632
- <MaintenanceIcon />
633
- Issues
634
- </ListItem>
635
- </List>
636
- </div>
637
-
638
- {/* Warning */}
639
- <div className="space-y-4">
640
- <h4 className="text-fm-secondary text-sm font-medium">Warning</h4>
641
- <List borderVariant="warning">
642
- <ListItem>
643
- <LightBulbSimpleIcon />
644
- Warning
645
- </ListItem>
646
- <ListItem>
647
- <MaintenanceIcon />
648
- Caution
649
- </ListItem>
650
- </List>
651
- </div>
652
-
653
- {/* Info */}
654
- <div className="space-y-4">
655
- <h4 className="text-fm-secondary text-sm font-medium">Info</h4>
656
- <List borderVariant="info">
657
- <ListItem>
658
- <FeatureShineIcon />
659
- Info
660
- </ListItem>
661
- <ListItem>
662
- <BubbleSparkleIcon />
663
- Details
664
- </ListItem>
665
- </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>
666
269
  </div>
667
270
  </div>
668
271
 
669
- {/* No Border */}
670
- <div className="mx-auto max-w-md">
671
- <h4 className="text-fm-secondary mb-4 text-sm font-medium">
672
- No Border
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
673
276
  </h4>
674
- <List showBorder={false}>
277
+ <List className="w-56">
675
278
  <ListItem>
676
- <SearchIcon />
677
- No top border
678
- </ListItem>
679
- <ListItem>
680
- <EyeOpenIcon />
681
- Clean look
279
+ <SearchIcon className="size-4" />
280
+ Search
682
281
  </ListItem>
282
+ <ListSubTrigger>
283
+ <SettingIcon className="size-4" />
284
+ More Options
285
+ </ListSubTrigger>
683
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>
684
294
  </div>
685
295
  </div>
686
296
  ),
687
297
  parameters: {
298
+ layout: "padded",
688
299
  docs: {
689
300
  description: {
690
301
  story:
691
- "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.",
692
303
  },
693
304
  },
694
305
  },
695
306
  }
696
307
 
697
- // 7. Custom Styling
698
- export const CustomStyling: Story = {
308
+ // ─── 2. AllVariants ───────────────────────────────────────────────────────────
309
+
310
+ export const AllVariants: Story = {
699
311
  render: () => (
700
- <div className="space-y-8 p-8">
701
- <h3 className="text-fm-primary text-center text-lg font-medium">
702
- Custom Styling
703
- </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>
704
342
 
705
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
706
- {/* Custom Classes */}
707
- <div className="space-y-4">
708
- <h4 className="text-fm-secondary text-sm font-medium">
709
- Custom Classes
710
- </h4>
711
- <List
712
- className="border-purple-500/30 bg-purple-900/10"
713
- classes={{
714
- root: "backdrop-blur-xl",
715
- border: "bg-gradient-to-r from-purple-500 to-pink-500",
716
- }}
717
- borderVariant="info"
718
- >
719
- <ListItem
720
- classes={{
721
- root: "hover:bg-purple-500/20 text-purple-100",
722
- }}
723
- >
724
- <FeatureShineIcon />
725
- Purple Theme
726
- </ListItem>
727
- <ListItem
728
- selected
729
- classes={{
730
- root: "bg-purple-500/30 text-white",
731
- }}
732
- >
733
- <BubbleSparkleIcon />
734
- Custom Selected
735
- </ListItem>
736
- <ListItem
737
- classes={{
738
- root: "hover:bg-purple-500/20 text-purple-100",
739
- }}
740
- >
741
- <MagicBookIcon />
742
- Magic Item
743
- </ListItem>
744
- </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
+ ))}
745
366
  </div>
367
+ </div>
746
368
 
747
- {/* Complex Layout */}
748
- <div className="space-y-4">
749
- <h4 className="text-fm-secondary text-sm font-medium">
750
- Complex Layout
751
- </h4>
752
- <List variant="elevated" size="lg">
753
- <ListLabel size="lg">Premium Features</ListLabel>
754
- <ListItem size="lg">
755
- <div className="flex items-center gap-3">
756
- <div className="rounded-full bg-green-500/20 p-2">
757
- <TickIcon className="text-fm-icon-positive size-4" />
758
- </div>
759
- <div className="flex-1">
760
- <div className="text-fm-primary font-medium">
761
- Advanced Analytics
762
- </div>
763
- <div className="text-fm-secondary text-xs">
764
- Deep insights and reporting
765
- </div>
766
- </div>
767
- <Badge color="positive">Active</Badge>
768
- </div>
769
- </ListItem>
770
- <ListItem size="lg">
771
- <div className="flex items-center gap-3">
772
- <div className="rounded-full bg-blue-500/20 p-2">
773
- <FeatureShineIcon className="text-fm-icon-info size-4" />
774
- </div>
775
- <div className="flex-1">
776
- <div className="text-fm-primary font-medium">
777
- AI Assistant
778
- </div>
779
- <div className="text-fm-secondary text-xs">
780
- Intelligent automation
781
- </div>
782
- </div>
783
- <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>
784
385
  </div>
785
- </ListItem>
786
- <ListItem size="lg" disabled>
787
- <div className="flex items-center gap-3">
788
- <div className="bg-fm-surface-secondary rounded-full p-2">
789
- <LightBulbSimpleIcon className="text-fm-tertiary size-4" />
790
- </div>
791
- <div className="flex-1">
792
- <div className="font-medium">Custom Workflows</div>
793
- <div className="text-fm-tertiary text-xs">Coming soon</div>
794
- </div>
795
- <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>
796
422
  </div>
797
- </ListItem>
798
- </List>
423
+ ))
424
+ )}
799
425
  </div>
800
426
  </div>
801
427
  </div>
802
428
  ),
803
429
  parameters: {
430
+ layout: "padded",
804
431
  docs: {
805
432
  description: {
806
433
  story:
807
- "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.",
808
435
  },
809
436
  },
810
437
  },
811
438
  }
812
439
 
813
- // 8. Interactive Showcase
814
- export const InteractiveShowcase: Story = {
440
+ // ─── 3. Interactive ───────────────────────────────────────────────────────────
441
+
442
+ export const Interactive: Story = {
815
443
  render: () => {
816
- const [selectedItems, setSelectedItems] = React.useState<string[]>([
817
- "item2",
818
- ])
819
- const [checkedFeatures, setCheckedFeatures] = React.useState<string[]>([
820
- "analytics",
444
+ const [enabledFeatures, setEnabledFeatures] = React.useState<string[]>([
445
+ "spatial",
446
+ "crossfade",
821
447
  ])
822
- const [theme, setTheme] = React.useState("dark")
448
+ const [audioQuality, setAudioQuality] = React.useState("high")
449
+ const [activeTab, setActiveTab] = React.useState("tracks")
823
450
 
824
- const handleItemSelect = (itemId: string) => {
825
- setSelectedItems([itemId])
451
+ const toggleFeature = (id: string, checked: boolean) => {
452
+ setEnabledFeatures((prev) =>
453
+ checked ? [...prev, id] : prev.filter((f) => f !== id)
454
+ )
826
455
  }
827
456
 
828
- const handleFeatureToggle = (featureId: string, checked: boolean) => {
829
- setCheckedFeatures((prev) =>
830
- checked ? [...prev, featureId] : prev.filter((id) => id !== featureId)
831
- )
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)",
832
462
  }
833
463
 
834
464
  return (
835
- <div className="space-y-8 p-8">
836
- <h3 className="text-fm-primary text-center text-lg font-medium">
837
- Interactive Showcase
838
- </h3>
839
-
840
- <div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
841
- {/* Navigation List */}
842
- <div className="space-y-4">
843
- <h4 className="text-fm-secondary text-sm font-medium">
844
- Navigation
845
- </h4>
846
- <List>
847
- <ListLabel>Main Menu</ListLabel>
848
- <ListItem
849
- selected={selectedItems.includes("item1")}
850
- onClick={() => handleItemSelect("item1")}
851
- className="cursor-pointer"
852
- >
853
- <FileChartIcon />
854
- Dashboard
855
- </ListItem>
856
- <ListItem
857
- selected={selectedItems.includes("item2")}
858
- onClick={() => handleItemSelect("item2")}
859
- className="cursor-pointer"
860
- >
861
- <ImageIcon />
862
- Media Library
863
- <Badge color="info" className="ml-auto">
864
- 12
865
- </Badge>
866
- </ListItem>
867
- <ListItem
868
- selected={selectedItems.includes("item3")}
869
- onClick={() => handleItemSelect("item3")}
870
- className="cursor-pointer"
871
- >
872
- <MaintenanceIcon />
873
- Settings
874
- </ListItem>
875
- <ListSeparator />
876
- <ListSubTrigger>
877
- <BubbleSparkleIcon />
878
- Advanced Options
879
- </ListSubTrigger>
880
- </List>
881
- </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>
882
520
 
883
- {/* Feature Selection */}
884
- <div className="space-y-4">
885
- <h4 className="text-fm-secondary text-sm font-medium">Features</h4>
886
- <List borderVariant="success">
887
- <ListLabel>Enable Features</ListLabel>
888
- <ListCheckboxItem
889
- checked={checkedFeatures.includes("analytics")}
890
- onCheckedChange={(checked) =>
891
- handleFeatureToggle("analytics", checked)
892
- }
893
- >
894
- <FeatureShineIcon />
895
- Analytics
896
- </ListCheckboxItem>
897
- <ListCheckboxItem
898
- checked={checkedFeatures.includes("ai")}
899
- onCheckedChange={(checked) =>
900
- handleFeatureToggle("ai", checked)
901
- }
902
- >
903
- <LightBulbSimpleIcon />
904
- AI Features
905
- </ListCheckboxItem>
906
- <ListCheckboxItem
907
- checked={checkedFeatures.includes("sync")}
908
- onCheckedChange={(checked) =>
909
- handleFeatureToggle("sync", checked)
910
- }
911
- >
912
- <BubbleSparkleIcon />
913
- Real-time Sync
914
- </ListCheckboxItem>
915
- </List>
916
- </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>
917
557
 
918
- {/* Theme Selection */}
919
- <div className="space-y-4">
920
- <h4 className="text-fm-secondary text-sm font-medium">Theme</h4>
921
- <List borderVariant="info">
922
- <ListLabel>Appearance</ListLabel>
923
- <ListRadioGroup value={theme}>
924
- <ListRadioItem value="light" onSelect={setTheme}>
925
- <EyeOpenIcon />
926
- Light Theme
927
- </ListRadioItem>
928
- <ListRadioItem value="dark" onSelect={setTheme}>
929
- <MaintenanceIcon />
930
- Dark Theme
931
- </ListRadioItem>
932
- <ListRadioItem value="auto" onSelect={setTheme}>
933
- <FeatureShineIcon />
934
- Auto Theme
935
- </ListRadioItem>
936
- </ListRadioGroup>
937
- </List>
938
- </div>
939
- </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>
940
580
 
941
- {/* Status Display */}
942
- <div className="border-fm-divider-secondary bg-fm-surface-secondary mx-auto max-w-2xl rounded-lg border p-4">
943
- <h4 className="text-fm-primary mb-3 text-sm font-medium">
944
- Current State
945
- </h4>
946
- <div className="text-fm-secondary grid grid-cols-1 gap-3 text-xs md:grid-cols-3">
947
- <div>
948
- <strong>Selected Page:</strong>{" "}
949
- {selectedItems.includes("item1")
950
- ? "Dashboard"
951
- : selectedItems.includes("item2")
952
- ? "Media Library"
953
- : selectedItems.includes("item3")
954
- ? "Settings"
955
- : "None"}
956
- </div>
957
- <div>
958
- <strong>Enabled Features:</strong>{" "}
959
- {checkedFeatures.length > 0 ? checkedFeatures.join(", ") : "None"}
960
- </div>
961
- <div>
962
- <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>
963
611
  </div>
964
612
  </div>
965
613
  </div>
@@ -967,10 +615,11 @@ export const InteractiveShowcase: Story = {
967
615
  )
968
616
  },
969
617
  parameters: {
618
+ layout: "fullscreen",
970
619
  docs: {
971
620
  description: {
972
621
  story:
973
- "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.",
974
623
  },
975
624
  },
976
625
  },