aural-ui 4.0.1 → 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 (174) hide show
  1. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
  2. package/dist/components/avatar/Avatar.stories.tsx +219 -235
  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/card/Card.stories.tsx +619 -301
  8. package/dist/components/char-count/CharCount.stories.tsx +350 -248
  9. package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
  10. package/dist/components/chip/Chip.stories.tsx +362 -168
  11. package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
  12. package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
  13. package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
  14. package/dist/components/command/Command.stories.tsx +530 -867
  15. package/dist/components/dialog/Dialog.stories.tsx +501 -950
  16. package/dist/components/divider/Divider.stories.tsx +264 -527
  17. package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
  18. package/dist/components/drawer/Drawer.stories.tsx +659 -1023
  19. package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
  20. package/dist/components/form/Form.stories.tsx +560 -274
  21. package/dist/components/helper-text/HelperText.stories.tsx +199 -200
  22. package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
  23. package/dist/components/icon-button/IconButton.stories.tsx +837 -194
  24. package/dist/components/if-else/if-else.stories.tsx +370 -83
  25. package/dist/components/input/Input.stories.tsx +436 -368
  26. package/dist/components/label/Label.stories.tsx +156 -154
  27. package/dist/components/list/List.stories.tsx +484 -835
  28. package/dist/components/marquee/Marquee.stories.tsx +356 -712
  29. package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
  30. package/dist/components/overlay/Overlay.stories.tsx +452 -824
  31. package/dist/components/pagination/Pagination.stories.tsx +721 -210
  32. package/dist/components/popover/Popover.stories.tsx +481 -896
  33. package/dist/components/radio/Radio.stories.tsx +432 -124
  34. package/dist/components/resizable/Resizable.stories.tsx +495 -799
  35. package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
  36. package/dist/components/search/Search.stories.tsx +312 -595
  37. package/dist/components/select/Select.stories.tsx +684 -789
  38. package/dist/components/sheet/Sheet.stories.tsx +671 -950
  39. package/dist/components/skelton/Skelton.stories.tsx +230 -764
  40. package/dist/components/slider/Slider.stories.tsx +383 -760
  41. package/dist/components/stepper/Stepper.stories.tsx +371 -514
  42. package/dist/components/switch/Switch.stories.tsx +461 -208
  43. package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
  44. package/dist/components/table/Table.stories.tsx +770 -916
  45. package/dist/components/tabs/Tabs.stories.tsx +458 -1455
  46. package/dist/components/tag/Tag.stories.tsx +714 -542
  47. package/dist/components/textarea/TextArea.stories.tsx +621 -562
  48. package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
  49. package/dist/components/toast/Toast.stories.tsx +452 -1339
  50. package/dist/components/toggle/Toggle.stories.tsx +488 -931
  51. package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
  52. package/dist/components/typography/Typography.stories.tsx +406 -89
  53. package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
  54. package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
  55. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
  56. package/dist/icons/Icons.stories.tsx +0 -12
  57. package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
  58. package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
  59. package/dist/icons/all-icons.tsx +37 -16
  60. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
  61. package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
  62. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
  63. package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
  64. package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
  65. package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
  66. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
  67. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
  68. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
  69. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
  70. package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
  71. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
  72. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
  73. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
  74. package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
  75. package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
  76. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
  77. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
  78. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
  79. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
  80. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
  81. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
  82. package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
  83. package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
  84. package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
  85. package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
  86. package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
  87. package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
  88. package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
  89. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
  90. package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
  91. package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
  92. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
  93. package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
  94. package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
  95. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
  96. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
  97. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
  98. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
  99. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
  100. package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
  101. package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
  102. package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
  103. package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
  104. package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
  105. package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
  106. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
  107. package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
  108. package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
  109. package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
  110. package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
  111. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
  112. package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
  113. package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
  114. package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
  115. package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
  116. package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
  117. package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
  118. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
  119. package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
  120. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
  121. package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
  122. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
  123. package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
  124. package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
  125. package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
  126. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
  127. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
  128. package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
  129. package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
  130. package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
  131. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
  132. package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
  133. package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
  134. package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
  135. package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
  136. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
  137. package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
  138. package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
  139. package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
  140. package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
  141. package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
  142. package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
  143. package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
  144. package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
  145. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
  146. package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
  147. package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
  148. package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
  149. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
  150. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
  151. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
  152. package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
  153. package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
  154. package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
  155. package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
  156. package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
  157. package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
  158. package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
  159. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
  160. package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
  161. package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
  162. package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
  163. package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
  164. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
  165. package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
  166. package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
  167. package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
  168. package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
  169. package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
  170. package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
  171. package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
  172. package/dist/index.cjs +1 -1
  173. package/dist/index.js +1 -1
  174. 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,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
  },