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.
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
- package/dist/components/avatar/Avatar.stories.tsx +219 -235
- package/dist/components/badge/Badge.stories.tsx +379 -116
- package/dist/components/banner/Banner.stories.tsx +445 -391
- package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
- package/dist/components/button/Button.stories.tsx +585 -230
- package/dist/components/card/Card.stories.tsx +619 -301
- package/dist/components/char-count/CharCount.stories.tsx +350 -248
- package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
- package/dist/components/chip/Chip.stories.tsx +362 -168
- package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
- package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
- package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
- package/dist/components/command/Command.stories.tsx +530 -867
- package/dist/components/dialog/Dialog.stories.tsx +501 -950
- package/dist/components/divider/Divider.stories.tsx +264 -527
- package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
- package/dist/components/drawer/Drawer.stories.tsx +659 -1023
- package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
- package/dist/components/form/Form.stories.tsx +560 -274
- package/dist/components/helper-text/HelperText.stories.tsx +199 -200
- package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
- package/dist/components/icon-button/IconButton.stories.tsx +837 -194
- package/dist/components/if-else/if-else.stories.tsx +370 -83
- package/dist/components/input/Input.stories.tsx +436 -368
- package/dist/components/label/Label.stories.tsx +156 -154
- package/dist/components/list/List.stories.tsx +484 -835
- package/dist/components/marquee/Marquee.stories.tsx +356 -712
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
- package/dist/components/overlay/Overlay.stories.tsx +452 -824
- package/dist/components/pagination/Pagination.stories.tsx +721 -210
- package/dist/components/popover/Popover.stories.tsx +481 -896
- package/dist/components/radio/Radio.stories.tsx +432 -124
- package/dist/components/resizable/Resizable.stories.tsx +495 -799
- package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
- package/dist/components/search/Search.stories.tsx +312 -595
- package/dist/components/select/Select.stories.tsx +684 -789
- package/dist/components/sheet/Sheet.stories.tsx +671 -950
- package/dist/components/skelton/Skelton.stories.tsx +230 -764
- package/dist/components/slider/Slider.stories.tsx +383 -760
- package/dist/components/stepper/Stepper.stories.tsx +371 -514
- package/dist/components/switch/Switch.stories.tsx +461 -208
- package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
- package/dist/components/table/Table.stories.tsx +770 -916
- package/dist/components/tabs/Tabs.stories.tsx +458 -1455
- package/dist/components/tag/Tag.stories.tsx +714 -542
- package/dist/components/textarea/TextArea.stories.tsx +621 -562
- package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
- package/dist/components/toast/Toast.stories.tsx +452 -1339
- package/dist/components/toggle/Toggle.stories.tsx +488 -931
- package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
- package/dist/components/typography/Typography.stories.tsx +406 -89
- package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
- package/dist/icons/Icons.stories.tsx +0 -12
- package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
- package/dist/icons/all-icons.tsx +37 -16
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
- package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
- package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
- package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
- package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
- package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
- package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
- package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
- package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
- package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
- package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
- package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
- package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
- package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
- package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
- package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
- package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
- package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
- package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
- package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
- package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
- package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
- package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
- package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
- package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
- package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
- package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
- package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
- package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
- package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
- package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
- package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
- package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
- package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
- package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
- package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
- package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
- package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
- package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
- package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
- package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
- package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
- package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
- package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
- package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
- package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
- package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
- package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
- package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
- package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
- package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
- package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
- package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
- package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
- package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
- package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
- package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
- package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
- package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
- package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
- package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
- package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
- package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
- package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
- package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
- package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
- package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
- package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
- package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
- package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
- package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
- package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- 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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
LightBulbSimpleIcon,
|
|
13
|
-
MagicBookIcon,
|
|
14
|
-
MaintenanceIcon,
|
|
5
|
+
HeartIcon,
|
|
6
|
+
MusicalNoteIcon,
|
|
7
|
+
PauseIcon,
|
|
15
8
|
SearchIcon,
|
|
16
|
-
|
|
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: "
|
|
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
|
-
|
|
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
|
|
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: "
|
|
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
|
|
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
|
|
82
|
+
description: "Color of the top accent border stripe",
|
|
169
83
|
},
|
|
170
84
|
showBorder: {
|
|
171
85
|
control: "boolean",
|
|
172
|
-
description: "
|
|
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.
|
|
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
|
-
|
|
223
|
-
export const GroupedList: Story = {
|
|
96
|
+
export const Parts: Story = {
|
|
224
97
|
render: () => (
|
|
225
|
-
<div className="mx-auto max-w-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
<ListItem>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
<
|
|
239
|
-
|
|
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
|
-
<
|
|
244
|
-
|
|
245
|
-
<span className="ml-auto text-xs opacity-60">⌘E</span>
|
|
155
|
+
<SkipForwardIcon className="size-4" />
|
|
156
|
+
Skip
|
|
246
157
|
</ListItem>
|
|
247
|
-
</
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
252
|
-
|
|
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
|
-
<
|
|
255
|
-
|
|
256
|
-
<Badge color="info" className="ml-auto">
|
|
257
|
-
New
|
|
258
|
-
</Badge>
|
|
175
|
+
<MusicalNoteIcon className="size-4" />
|
|
176
|
+
Default
|
|
259
177
|
</ListItem>
|
|
260
|
-
<ListItem>
|
|
261
|
-
<
|
|
262
|
-
|
|
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
|
-
|
|
277
|
-
<span className="ml-auto text-xs opacity-60">⌘⌫</span>
|
|
187
|
+
<TrashIcon className="size-4" />
|
|
188
|
+
Destructive
|
|
278
189
|
</ListItem>
|
|
279
|
-
</
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
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
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
</
|
|
550
|
-
<
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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
|
-
{/*
|
|
670
|
-
<div className="
|
|
671
|
-
<h4 className="text-fm-secondary
|
|
672
|
-
|
|
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
|
|
277
|
+
<List className="w-56">
|
|
675
278
|
<ListItem>
|
|
676
|
-
<SearchIcon />
|
|
677
|
-
|
|
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
|
-
"
|
|
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
|
-
//
|
|
698
|
-
|
|
308
|
+
// ─── 2. AllVariants ───────────────────────────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
export const AllVariants: Story = {
|
|
699
311
|
render: () => (
|
|
700
|
-
<div className="space-y-8
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
-
|
|
706
|
-
|
|
707
|
-
<
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
className="
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
</
|
|
727
|
-
|
|
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
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
<div className="
|
|
756
|
-
<
|
|
757
|
-
<
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
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
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
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
|
-
|
|
798
|
-
|
|
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
|
-
"
|
|
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
|
-
//
|
|
814
|
-
|
|
440
|
+
// ─── 3. Interactive ───────────────────────────────────────────────────────────
|
|
441
|
+
|
|
442
|
+
export const Interactive: Story = {
|
|
815
443
|
render: () => {
|
|
816
|
-
const [
|
|
817
|
-
"
|
|
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 [
|
|
448
|
+
const [audioQuality, setAudioQuality] = React.useState("high")
|
|
449
|
+
const [activeTab, setActiveTab] = React.useState("tracks")
|
|
823
450
|
|
|
824
|
-
const
|
|
825
|
-
|
|
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
|
|
829
|
-
|
|
830
|
-
|
|
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="
|
|
836
|
-
<
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
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
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
<
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
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
|
|
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
|
},
|