aural-ui 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- 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 +90 -90
- package/dist/index.js +90 -90
- package/package.json +8 -3
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
import React, { useState } from "react"
|
|
2
2
|
import { Button } from "@components/button"
|
|
3
|
-
import { IconButton } from "@components/icon-button"
|
|
4
3
|
import {
|
|
5
|
-
AlertIcon,
|
|
6
4
|
AngleDownIcon,
|
|
7
|
-
ArrowRightIcon,
|
|
8
5
|
AudioBarIcon,
|
|
9
6
|
ChevronDownIcon,
|
|
10
|
-
|
|
7
|
+
CircleTickIcon,
|
|
8
|
+
DownloadIcon,
|
|
11
9
|
EditBigIcon,
|
|
12
|
-
EyeCloseIcon,
|
|
13
10
|
EyeOpenIcon,
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
FileTextIcon,
|
|
12
|
+
HeartIcon,
|
|
13
|
+
MaintenanceIcon,
|
|
14
|
+
MusicalNoteIcon,
|
|
16
15
|
PlusIcon,
|
|
17
16
|
SearchIcon,
|
|
18
|
-
|
|
17
|
+
ShareIcon,
|
|
18
|
+
StarIcon,
|
|
19
19
|
TickIcon,
|
|
20
20
|
TrashIcon,
|
|
21
21
|
UploadIcon,
|
|
22
|
+
VerticalMenuIcon,
|
|
22
23
|
} from "@icons/index"
|
|
23
24
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
24
25
|
|
|
26
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
27
|
+
|
|
25
28
|
import {
|
|
26
|
-
DropdownArrow,
|
|
27
29
|
DropdownMenu,
|
|
28
30
|
DropdownMenuCheckboxItem,
|
|
29
31
|
DropdownMenuContent,
|
|
@@ -45,86 +47,29 @@ const meta: Meta<typeof DropdownMenu> = {
|
|
|
45
47
|
component: DropdownMenu,
|
|
46
48
|
parameters: {
|
|
47
49
|
layout: "centered",
|
|
48
|
-
backgrounds: {
|
|
49
|
-
default: "dark",
|
|
50
|
-
values: [
|
|
51
|
-
{ name: "dark", value: "#0a0a0a" },
|
|
52
|
-
{ name: "light", value: "#ffffff" },
|
|
53
|
-
],
|
|
54
|
-
},
|
|
55
50
|
docs: {
|
|
56
51
|
description: {
|
|
57
|
-
component:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
A comprehensive dropdown menu component system built on Radix UI with dark theme optimization and frosted glass effects.
|
|
61
|
-
|
|
62
|
-
## Features
|
|
63
|
-
|
|
64
|
-
- **Dark Theme Optimized**: Frosted glass background with gradient borders
|
|
65
|
-
- **Flexible Content**: Support for items, labels, separators, checkboxes, and radio groups
|
|
66
|
-
- **Nested Menus**: Sub-menu support with hover triggers
|
|
67
|
-
- **Icon Integration**: Built-in icon support with proper sizing and theming
|
|
68
|
-
- **Keyboard Navigation**: Full accessibility with arrow keys and shortcuts
|
|
69
|
-
- **Custom Styling**: Granular control via \`classes\` prop
|
|
70
|
-
- **Smooth Animations**: Direction-aware entrance/exit animations
|
|
71
|
-
- **Portal Rendering**: Proper z-index layering and positioning
|
|
72
|
-
- **Logical Grouping**: Use \`DropdownMenuGroup\` for semantic organization
|
|
73
|
-
|
|
74
|
-
## Component Structure
|
|
75
|
-
|
|
76
|
-
- **DropdownMenu**: Root container managing state
|
|
77
|
-
- **DropdownMenuTrigger**: Interactive element that opens the menu
|
|
78
|
-
- **DropdownMenuContent**: The floating menu panel with frosted glass effect
|
|
79
|
-
- **DropdownMenuItem**: Standard menu item with optional variants
|
|
80
|
-
- **DropdownMenuGroup**: Groups related menu items together
|
|
81
|
-
- **DropdownMenuLabel**: Section headers and labels
|
|
82
|
-
- **DropdownMenuSeparator**: Visual dividers between sections
|
|
83
|
-
- **DropdownMenuCheckboxItem**: Checkable items with indicators
|
|
84
|
-
- **DropdownMenuRadioGroup/RadioItem**: Radio button groups
|
|
85
|
-
- **DropdownMenuSub/SubTrigger/SubContent**: Nested sub-menus
|
|
86
|
-
- **DropdownMenuShortcut**: Keyboard shortcut display
|
|
87
|
-
|
|
88
|
-
## Usage Examples
|
|
89
|
-
|
|
90
|
-
### Basic Menu with Groups
|
|
91
|
-
\`\`\`tsx
|
|
92
|
-
<DropdownMenu>
|
|
93
|
-
<DropdownMenuTrigger asChild>
|
|
94
|
-
<Button>Open Menu</Button>
|
|
95
|
-
</DropdownMenuTrigger>
|
|
96
|
-
<DropdownMenuContent>
|
|
97
|
-
<DropdownMenuGroup>
|
|
98
|
-
<DropdownMenuItem>Edit</DropdownMenuItem>
|
|
99
|
-
<DropdownMenuItem>Copy</DropdownMenuItem>
|
|
100
|
-
</DropdownMenuGroup>
|
|
101
|
-
<DropdownMenuSeparator />
|
|
102
|
-
<DropdownMenuGroup>
|
|
103
|
-
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
|
|
104
|
-
</DropdownMenuGroup>
|
|
105
|
-
</DropdownMenuContent>
|
|
106
|
-
</DropdownMenu>
|
|
107
|
-
\`\`\`
|
|
108
|
-
|
|
109
|
-
### With Custom Styling
|
|
110
|
-
\`\`\`tsx
|
|
111
|
-
<DropdownMenuContent
|
|
112
|
-
classes={{
|
|
113
|
-
root: "bg-blue-900/20",
|
|
114
|
-
border: "bg-gradient-to-r from-blue-500 to-purple-500"
|
|
115
|
-
}}
|
|
116
|
-
>
|
|
117
|
-
<DropdownMenuItem
|
|
118
|
-
classes={{
|
|
119
|
-
root: "text-blue-400 hover:bg-blue-500/20"
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
122
|
-
Custom Item
|
|
123
|
-
</DropdownMenuItem>
|
|
124
|
-
</DropdownMenuContent>
|
|
125
|
-
\`\`\`
|
|
126
|
-
`,
|
|
52
|
+
component:
|
|
53
|
+
"A comprehensive dropdown menu system built on Radix UI with a frosted-glass aesthetic and gradient top border. Supports standard items, checkboxes, radio groups, nested sub-menus, separators, keyboard shortcuts, and a destructive variant. All item types accept a `classes` prop for granular style overrides. Animations are direction-aware and the menu renders into a portal for correct z-index layering.",
|
|
127
54
|
},
|
|
55
|
+
page: () => (
|
|
56
|
+
<AuralComponentDocsPage
|
|
57
|
+
features={[
|
|
58
|
+
{
|
|
59
|
+
title: "Rich Item Types",
|
|
60
|
+
description: "Checkbox, radio, sub-menu",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: "Keyboard Shortcuts",
|
|
64
|
+
description: "Shortcut slot per item",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: "Destructive Variant",
|
|
68
|
+
description: "Red danger action style",
|
|
69
|
+
},
|
|
70
|
+
]}
|
|
71
|
+
/>
|
|
72
|
+
),
|
|
128
73
|
},
|
|
129
74
|
},
|
|
130
75
|
tags: ["autodocs"],
|
|
@@ -133,678 +78,497 @@ A comprehensive dropdown menu component system built on Radix UI with dark theme
|
|
|
133
78
|
export default meta
|
|
134
79
|
type Story = StoryObj<typeof DropdownMenu>
|
|
135
80
|
|
|
136
|
-
//
|
|
137
|
-
|
|
81
|
+
// ─── Configurations ───────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
export const Configurations: Story = {
|
|
138
84
|
render: () => (
|
|
139
85
|
<div className="space-y-8">
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
Simple dropdown menus with different trigger styles and grouped
|
|
146
|
-
content
|
|
147
|
-
</p>
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
<div className="flex flex-wrap items-start justify-center gap-4">
|
|
151
|
-
{/* Basic Button Trigger */}
|
|
152
|
-
<DropdownMenu>
|
|
153
|
-
<DropdownMenuTrigger asChild>
|
|
154
|
-
<Button variant="outline" className="gap-2">
|
|
155
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
156
|
-
Options
|
|
157
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
158
|
-
</Button>
|
|
159
|
-
</DropdownMenuTrigger>
|
|
160
|
-
<DropdownMenuContent>
|
|
161
|
-
<DropdownMenuGroup>
|
|
162
|
-
<DropdownMenuItem>
|
|
163
|
-
<EditBigIcon className="h-4 w-4" />
|
|
164
|
-
Edit
|
|
165
|
-
</DropdownMenuItem>
|
|
166
|
-
<DropdownMenuItem>
|
|
167
|
-
<TickIcon className="h-4 w-4" />
|
|
168
|
-
Copy
|
|
169
|
-
</DropdownMenuItem>
|
|
170
|
-
</DropdownMenuGroup>
|
|
171
|
-
<DropdownMenuSeparator />
|
|
172
|
-
<DropdownMenuGroup>
|
|
173
|
-
<DropdownMenuItem variant="destructive">
|
|
174
|
-
<TrashIcon className="h-4 w-4" />
|
|
175
|
-
Delete
|
|
176
|
-
</DropdownMenuItem>
|
|
177
|
-
</DropdownMenuGroup>
|
|
178
|
-
</DropdownMenuContent>
|
|
179
|
-
</DropdownMenu>
|
|
180
|
-
|
|
181
|
-
{/* Icon Button Trigger */}
|
|
182
|
-
<DropdownMenu>
|
|
183
|
-
<DropdownMenuTrigger asChild>
|
|
184
|
-
<IconButton variant="ghost" icon={<AlertIcon />} label="" />
|
|
185
|
-
</DropdownMenuTrigger>
|
|
186
|
-
<DropdownMenuContent>
|
|
187
|
-
<DropdownMenuGroup>
|
|
188
|
-
<DropdownMenuItem>
|
|
189
|
-
<ArrowRightIcon className="h-4 w-4" />
|
|
190
|
-
Share
|
|
191
|
-
</DropdownMenuItem>
|
|
192
|
-
<DropdownMenuItem>
|
|
193
|
-
<TickIcon className="h-4 w-4" />
|
|
194
|
-
Favorite
|
|
195
|
-
</DropdownMenuItem>
|
|
196
|
-
<DropdownMenuItem>
|
|
197
|
-
<TickIcon className="h-4 w-4" />
|
|
198
|
-
Copy Link
|
|
199
|
-
</DropdownMenuItem>
|
|
200
|
-
</DropdownMenuGroup>
|
|
201
|
-
</DropdownMenuContent>
|
|
202
|
-
</DropdownMenu>
|
|
203
|
-
|
|
204
|
-
{/* User Menu */}
|
|
205
|
-
<DropdownMenu>
|
|
206
|
-
<DropdownMenuTrigger asChild>
|
|
207
|
-
<Button variant="text" className="gap-2">
|
|
208
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
209
|
-
Account
|
|
210
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
211
|
-
</Button>
|
|
212
|
-
</DropdownMenuTrigger>
|
|
213
|
-
<DropdownMenuContent align="end">
|
|
214
|
-
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
215
|
-
<DropdownMenuSeparator />
|
|
216
|
-
<DropdownMenuGroup>
|
|
217
|
-
<DropdownMenuItem>
|
|
218
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
219
|
-
Profile
|
|
220
|
-
</DropdownMenuItem>
|
|
221
|
-
<DropdownMenuItem>
|
|
222
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
223
|
-
Settings
|
|
224
|
-
</DropdownMenuItem>
|
|
225
|
-
</DropdownMenuGroup>
|
|
226
|
-
<DropdownMenuSeparator />
|
|
227
|
-
<DropdownMenuGroup>
|
|
228
|
-
<DropdownMenuItem variant="destructive">
|
|
229
|
-
<CrossIcon className="h-4 w-4" />
|
|
230
|
-
Log out
|
|
231
|
-
</DropdownMenuItem>
|
|
232
|
-
</DropdownMenuGroup>
|
|
233
|
-
</DropdownMenuContent>
|
|
234
|
-
</DropdownMenu>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
),
|
|
238
|
-
parameters: {
|
|
239
|
-
docs: {
|
|
240
|
-
description: {
|
|
241
|
-
story:
|
|
242
|
-
"Basic dropdown menu examples with different trigger styles and grouped content using DropdownMenuGroup.",
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// 2. Interactive States
|
|
249
|
-
export const InteractiveStates: Story = {
|
|
250
|
-
render: () => {
|
|
251
|
-
const [notifications, setNotifications] = useState(true)
|
|
252
|
-
const [marketing, setMarketing] = useState(false)
|
|
253
|
-
const [theme, setTheme] = useState("dark")
|
|
254
|
-
|
|
255
|
-
return (
|
|
256
|
-
<div className="space-y-8">
|
|
257
|
-
<div className="text-center">
|
|
258
|
-
<h3 className="text-fm-primary mb-2 font-medium">
|
|
259
|
-
Interactive States
|
|
260
|
-
</h3>
|
|
261
|
-
<p className="text-fm-secondary text-sm">
|
|
262
|
-
Checkboxes, radio groups, and stateful interactions with logical
|
|
263
|
-
grouping
|
|
264
|
-
</p>
|
|
265
|
-
</div>
|
|
266
|
-
|
|
86
|
+
{/* Basic item */}
|
|
87
|
+
<div className="space-y-3">
|
|
88
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
89
|
+
Basic Items
|
|
90
|
+
</h4>
|
|
267
91
|
<div className="flex flex-wrap justify-center gap-4">
|
|
268
|
-
{/* Checkbox Menu */}
|
|
269
92
|
<DropdownMenu>
|
|
270
93
|
<DropdownMenuTrigger asChild>
|
|
271
|
-
<Button
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
94
|
+
<Button
|
|
95
|
+
variant="outline"
|
|
96
|
+
innerClassName="flex items-center gap-2"
|
|
97
|
+
>
|
|
98
|
+
Options
|
|
99
|
+
<ChevronDownIcon className="size-4" />
|
|
275
100
|
</Button>
|
|
276
101
|
</DropdownMenuTrigger>
|
|
277
102
|
<DropdownMenuContent>
|
|
278
|
-
<
|
|
103
|
+
<DropdownMenuGroup>
|
|
104
|
+
<DropdownMenuItem>
|
|
105
|
+
<EditBigIcon />
|
|
106
|
+
Edit
|
|
107
|
+
</DropdownMenuItem>
|
|
108
|
+
<DropdownMenuItem>
|
|
109
|
+
<TickIcon />
|
|
110
|
+
Duplicate
|
|
111
|
+
</DropdownMenuItem>
|
|
112
|
+
<DropdownMenuItem>
|
|
113
|
+
<ShareIcon />
|
|
114
|
+
Share
|
|
115
|
+
<DropdownMenuShortcut>⌘⇧S</DropdownMenuShortcut>
|
|
116
|
+
</DropdownMenuItem>
|
|
117
|
+
</DropdownMenuGroup>
|
|
279
118
|
<DropdownMenuSeparator />
|
|
280
119
|
<DropdownMenuGroup>
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
</DropdownMenuCheckboxItem>
|
|
287
|
-
<DropdownMenuCheckboxItem
|
|
288
|
-
checked={marketing}
|
|
289
|
-
onCheckedChange={setMarketing}
|
|
290
|
-
>
|
|
291
|
-
Marketing Emails
|
|
292
|
-
</DropdownMenuCheckboxItem>
|
|
120
|
+
<DropdownMenuItem variant="destructive">
|
|
121
|
+
<TrashIcon />
|
|
122
|
+
Delete
|
|
123
|
+
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
|
124
|
+
</DropdownMenuItem>
|
|
293
125
|
</DropdownMenuGroup>
|
|
294
126
|
</DropdownMenuContent>
|
|
295
127
|
</DropdownMenu>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
296
130
|
|
|
297
|
-
|
|
131
|
+
{/* Inset items */}
|
|
132
|
+
<div className="space-y-3">
|
|
133
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
134
|
+
Inset Items
|
|
135
|
+
</h4>
|
|
136
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
298
137
|
<DropdownMenu>
|
|
299
138
|
<DropdownMenuTrigger asChild>
|
|
300
|
-
<Button
|
|
301
|
-
|
|
302
|
-
|
|
139
|
+
<Button
|
|
140
|
+
variant="outline"
|
|
141
|
+
innerClassName="flex items-center gap-2"
|
|
142
|
+
>
|
|
143
|
+
With Inset
|
|
144
|
+
<ChevronDownIcon className="size-4" />
|
|
303
145
|
</Button>
|
|
304
146
|
</DropdownMenuTrigger>
|
|
305
|
-
<DropdownMenuContent>
|
|
306
|
-
<DropdownMenuLabel>
|
|
147
|
+
<DropdownMenuContent className="w-48">
|
|
148
|
+
<DropdownMenuLabel>Account</DropdownMenuLabel>
|
|
307
149
|
<DropdownMenuSeparator />
|
|
308
150
|
<DropdownMenuGroup>
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
</DropdownMenuRadioItem>
|
|
319
|
-
</DropdownMenuRadioGroup>
|
|
151
|
+
<DropdownMenuItem inset>Profile</DropdownMenuItem>
|
|
152
|
+
<DropdownMenuItem inset>Settings</DropdownMenuItem>
|
|
153
|
+
<DropdownMenuItem inset>Billing</DropdownMenuItem>
|
|
154
|
+
</DropdownMenuGroup>
|
|
155
|
+
<DropdownMenuSeparator />
|
|
156
|
+
<DropdownMenuGroup>
|
|
157
|
+
<DropdownMenuItem inset variant="destructive">
|
|
158
|
+
Log out
|
|
159
|
+
</DropdownMenuItem>
|
|
320
160
|
</DropdownMenuGroup>
|
|
321
161
|
</DropdownMenuContent>
|
|
322
162
|
</DropdownMenu>
|
|
323
163
|
</div>
|
|
324
|
-
|
|
325
|
-
{/* State Display */}
|
|
326
|
-
<div className="text-center">
|
|
327
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary inline-block rounded-lg border p-4">
|
|
328
|
-
<h4 className="text-fm-primary mb-2 text-sm font-medium">
|
|
329
|
-
Current State
|
|
330
|
-
</h4>
|
|
331
|
-
<div className="text-fm-secondary space-y-1 text-xs">
|
|
332
|
-
<div>Notifications: {notifications ? "On" : "Off"}</div>
|
|
333
|
-
<div>Marketing: {marketing ? "On" : "Off"}</div>
|
|
334
|
-
<div>Theme: {theme}</div>
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
337
|
-
</div>
|
|
338
|
-
</div>
|
|
339
|
-
)
|
|
340
|
-
},
|
|
341
|
-
parameters: {
|
|
342
|
-
docs: {
|
|
343
|
-
description: {
|
|
344
|
-
story:
|
|
345
|
-
"Interactive dropdown menus with checkboxes, radio groups, and state management using proper grouping.",
|
|
346
|
-
},
|
|
347
|
-
},
|
|
348
|
-
},
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// 3. Nested Sub-menus
|
|
352
|
-
export const NestedMenus: Story = {
|
|
353
|
-
render: () => (
|
|
354
|
-
<div className="space-y-8">
|
|
355
|
-
<div className="text-center">
|
|
356
|
-
<h3 className="text-fm-primary mb-2 font-medium">Nested Sub-menus</h3>
|
|
357
|
-
<p className="text-fm-secondary text-sm">
|
|
358
|
-
Multi-level menus with sub-menu navigation and logical grouping
|
|
359
|
-
</p>
|
|
360
|
-
</div>
|
|
361
|
-
|
|
362
|
-
<div className="flex justify-center">
|
|
363
|
-
<DropdownMenu>
|
|
364
|
-
<DropdownMenuTrigger asChild>
|
|
365
|
-
<Button variant="outline" className="gap-2">
|
|
366
|
-
<PlusIcon className="h-4 w-4" />
|
|
367
|
-
Create New
|
|
368
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
369
|
-
</Button>
|
|
370
|
-
</DropdownMenuTrigger>
|
|
371
|
-
<DropdownMenuContent>
|
|
372
|
-
<DropdownMenuLabel>Create</DropdownMenuLabel>
|
|
373
|
-
<DropdownMenuSeparator />
|
|
374
|
-
|
|
375
|
-
<DropdownMenuGroup>
|
|
376
|
-
<DropdownMenuSub>
|
|
377
|
-
<DropdownMenuSubTrigger>
|
|
378
|
-
<FileChartIcon className="h-4 w-4" />
|
|
379
|
-
Folder
|
|
380
|
-
</DropdownMenuSubTrigger>
|
|
381
|
-
<DropdownMenuSubContent>
|
|
382
|
-
<DropdownMenuGroup>
|
|
383
|
-
<DropdownMenuItem>
|
|
384
|
-
<FileChartIcon className="h-4 w-4" />
|
|
385
|
-
Project Folder
|
|
386
|
-
</DropdownMenuItem>
|
|
387
|
-
<DropdownMenuItem>
|
|
388
|
-
<FileChartIcon className="h-4 w-4" />
|
|
389
|
-
Asset Folder
|
|
390
|
-
</DropdownMenuItem>
|
|
391
|
-
<DropdownMenuItem>
|
|
392
|
-
<FileChartIcon className="h-4 w-4" />
|
|
393
|
-
Template Folder
|
|
394
|
-
</DropdownMenuItem>
|
|
395
|
-
</DropdownMenuGroup>
|
|
396
|
-
</DropdownMenuSubContent>
|
|
397
|
-
</DropdownMenuSub>
|
|
398
|
-
|
|
399
|
-
<DropdownMenuSub>
|
|
400
|
-
<DropdownMenuSubTrigger>
|
|
401
|
-
<FileChartIcon className="h-4 w-4" />
|
|
402
|
-
Document
|
|
403
|
-
</DropdownMenuSubTrigger>
|
|
404
|
-
<DropdownMenuSubContent>
|
|
405
|
-
<DropdownMenuGroup>
|
|
406
|
-
<DropdownMenuItem>
|
|
407
|
-
<FileChartIcon className="h-4 w-4" />
|
|
408
|
-
Text Document
|
|
409
|
-
</DropdownMenuItem>
|
|
410
|
-
<DropdownMenuItem>
|
|
411
|
-
<FileChartIcon className="h-4 w-4" />
|
|
412
|
-
Spreadsheet
|
|
413
|
-
</DropdownMenuItem>
|
|
414
|
-
<DropdownMenuItem>
|
|
415
|
-
<FileChartIcon className="h-4 w-4" />
|
|
416
|
-
Presentation
|
|
417
|
-
</DropdownMenuItem>
|
|
418
|
-
</DropdownMenuGroup>
|
|
419
|
-
<DropdownMenuSeparator />
|
|
420
|
-
<DropdownMenuGroup>
|
|
421
|
-
<DropdownMenuItem>
|
|
422
|
-
<ImageIcon className="h-4 w-4" />
|
|
423
|
-
From Template
|
|
424
|
-
</DropdownMenuItem>
|
|
425
|
-
</DropdownMenuGroup>
|
|
426
|
-
</DropdownMenuSubContent>
|
|
427
|
-
</DropdownMenuSub>
|
|
428
|
-
</DropdownMenuGroup>
|
|
429
|
-
|
|
430
|
-
<DropdownMenuSeparator />
|
|
431
|
-
<DropdownMenuGroup>
|
|
432
|
-
<DropdownMenuItem>
|
|
433
|
-
<UploadIcon className="h-4 w-4" />
|
|
434
|
-
Upload File
|
|
435
|
-
</DropdownMenuItem>
|
|
436
|
-
</DropdownMenuGroup>
|
|
437
|
-
</DropdownMenuContent>
|
|
438
|
-
</DropdownMenu>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
),
|
|
442
|
-
parameters: {
|
|
443
|
-
docs: {
|
|
444
|
-
description: {
|
|
445
|
-
story:
|
|
446
|
-
"Nested dropdown menus with sub-menu triggers and multi-level navigation using DropdownMenuGroup for organization.",
|
|
447
|
-
},
|
|
448
|
-
},
|
|
449
|
-
},
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// 4. Keyboard Shortcuts
|
|
453
|
-
export const KeyboardShortcuts: Story = {
|
|
454
|
-
render: () => (
|
|
455
|
-
<div className="space-y-8">
|
|
456
|
-
<div className="text-center">
|
|
457
|
-
<h3 className="text-fm-primary mb-2 font-medium">Keyboard Shortcuts</h3>
|
|
458
|
-
<p className="text-fm-secondary text-sm">
|
|
459
|
-
Menu items with keyboard shortcut indicators and logical grouping
|
|
460
|
-
</p>
|
|
461
|
-
</div>
|
|
462
|
-
|
|
463
|
-
<div className="flex justify-center">
|
|
464
|
-
<DropdownMenu>
|
|
465
|
-
<DropdownMenuTrigger asChild>
|
|
466
|
-
<Button variant="outline" className="gap-2">
|
|
467
|
-
<EditBigIcon className="h-4 w-4" />
|
|
468
|
-
Edit Menu
|
|
469
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
470
|
-
</Button>
|
|
471
|
-
</DropdownMenuTrigger>
|
|
472
|
-
<DropdownMenuContent className="w-56">
|
|
473
|
-
<DropdownMenuLabel>Edit</DropdownMenuLabel>
|
|
474
|
-
<DropdownMenuSeparator />
|
|
475
|
-
|
|
476
|
-
<DropdownMenuGroup>
|
|
477
|
-
<DropdownMenuItem>
|
|
478
|
-
<EditBigIcon className="h-4 w-4" />
|
|
479
|
-
Undo
|
|
480
|
-
<DropdownMenuShortcut>⌘Z</DropdownMenuShortcut>
|
|
481
|
-
</DropdownMenuItem>
|
|
482
|
-
<DropdownMenuItem>
|
|
483
|
-
<EditBigIcon className="h-4 w-4" />
|
|
484
|
-
Redo
|
|
485
|
-
<DropdownMenuShortcut>⌘⇧Z</DropdownMenuShortcut>
|
|
486
|
-
</DropdownMenuItem>
|
|
487
|
-
</DropdownMenuGroup>
|
|
488
|
-
|
|
489
|
-
<DropdownMenuSeparator />
|
|
490
|
-
|
|
491
|
-
<DropdownMenuGroup>
|
|
492
|
-
<DropdownMenuItem>
|
|
493
|
-
<TickIcon className="h-4 w-4" />
|
|
494
|
-
Cut
|
|
495
|
-
<DropdownMenuShortcut>⌘X</DropdownMenuShortcut>
|
|
496
|
-
</DropdownMenuItem>
|
|
497
|
-
<DropdownMenuItem>
|
|
498
|
-
<TickIcon className="h-4 w-4" />
|
|
499
|
-
Copy
|
|
500
|
-
<DropdownMenuShortcut>⌘C</DropdownMenuShortcut>
|
|
501
|
-
</DropdownMenuItem>
|
|
502
|
-
<DropdownMenuItem>
|
|
503
|
-
<TickIcon className="h-4 w-4" />
|
|
504
|
-
Paste
|
|
505
|
-
<DropdownMenuShortcut>⌘V</DropdownMenuShortcut>
|
|
506
|
-
</DropdownMenuItem>
|
|
507
|
-
</DropdownMenuGroup>
|
|
508
|
-
|
|
509
|
-
<DropdownMenuSeparator />
|
|
510
|
-
|
|
511
|
-
<DropdownMenuGroup>
|
|
512
|
-
<DropdownMenuItem>
|
|
513
|
-
Select All
|
|
514
|
-
<DropdownMenuShortcut>⌘A</DropdownMenuShortcut>
|
|
515
|
-
</DropdownMenuItem>
|
|
516
|
-
<DropdownMenuItem>
|
|
517
|
-
<SearchIcon className="h-4 w-4" />
|
|
518
|
-
Find
|
|
519
|
-
<DropdownMenuShortcut>⌘F</DropdownMenuShortcut>
|
|
520
|
-
</DropdownMenuItem>
|
|
521
|
-
</DropdownMenuGroup>
|
|
522
|
-
</DropdownMenuContent>
|
|
523
|
-
</DropdownMenu>
|
|
524
|
-
</div>
|
|
525
|
-
</div>
|
|
526
|
-
),
|
|
527
|
-
parameters: {
|
|
528
|
-
docs: {
|
|
529
|
-
description: {
|
|
530
|
-
story:
|
|
531
|
-
"Dropdown menu with keyboard shortcut indicators for common actions, organized with DropdownMenuGroup.",
|
|
532
|
-
},
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// 5. Custom Styling
|
|
538
|
-
export const CustomStyling: Story = {
|
|
539
|
-
render: () => (
|
|
540
|
-
<div className="space-y-8">
|
|
541
|
-
<div className="text-center">
|
|
542
|
-
<h3 className="text-fm-primary mb-2 font-medium">Custom Styling</h3>
|
|
543
|
-
<p className="text-fm-secondary text-sm">
|
|
544
|
-
Dropdown menus with custom styling using the classes prop
|
|
545
|
-
</p>
|
|
546
|
-
</div>
|
|
547
|
-
|
|
548
|
-
<div className="flex flex-wrap justify-center gap-4">
|
|
549
|
-
{/* Blue Theme */}
|
|
550
|
-
<DropdownMenu>
|
|
551
|
-
<DropdownMenuTrigger asChild>
|
|
552
|
-
<Button>Blue Theme</Button>
|
|
553
|
-
</DropdownMenuTrigger>
|
|
554
|
-
<DropdownMenuContent
|
|
555
|
-
classes={{
|
|
556
|
-
root: "bg-blue-900/40 border-blue-500/20",
|
|
557
|
-
border: "bg-gradient-to-r from-blue-500 to-cyan-500",
|
|
558
|
-
}}
|
|
559
|
-
>
|
|
560
|
-
<DropdownMenuGroup>
|
|
561
|
-
<DropdownMenuItem
|
|
562
|
-
classes={{
|
|
563
|
-
root: "text-blue-200 hover:bg-blue-500/20 focus:bg-blue-500/20",
|
|
564
|
-
}}
|
|
565
|
-
>
|
|
566
|
-
<TickIcon className="h-4 w-4" />
|
|
567
|
-
Blue Item
|
|
568
|
-
</DropdownMenuItem>
|
|
569
|
-
<DropdownMenuItem
|
|
570
|
-
classes={{
|
|
571
|
-
root: "text-blue-200 hover:bg-blue-500/20 focus:bg-blue-500/20",
|
|
572
|
-
}}
|
|
573
|
-
>
|
|
574
|
-
<AudioBarIcon className="h-4 w-4" />
|
|
575
|
-
Another Item
|
|
576
|
-
</DropdownMenuItem>
|
|
577
|
-
</DropdownMenuGroup>
|
|
578
|
-
</DropdownMenuContent>
|
|
579
|
-
</DropdownMenu>
|
|
580
|
-
|
|
581
|
-
{/* Green Theme */}
|
|
582
|
-
<DropdownMenu>
|
|
583
|
-
<DropdownMenuTrigger asChild>
|
|
584
|
-
<Button>Green Theme</Button>
|
|
585
|
-
</DropdownMenuTrigger>
|
|
586
|
-
<DropdownMenuContent
|
|
587
|
-
classes={{
|
|
588
|
-
root: "bg-green-900/40 border-green-500/20",
|
|
589
|
-
border: "bg-gradient-to-r from-green-500 to-emerald-500",
|
|
590
|
-
}}
|
|
591
|
-
>
|
|
592
|
-
<DropdownMenuGroup>
|
|
593
|
-
<DropdownMenuItem
|
|
594
|
-
classes={{
|
|
595
|
-
root: "text-green-200 hover:bg-green-500/20 focus:bg-green-500/20",
|
|
596
|
-
}}
|
|
597
|
-
>
|
|
598
|
-
<TickIcon className="h-4 w-4" />
|
|
599
|
-
Green Item
|
|
600
|
-
</DropdownMenuItem>
|
|
601
|
-
<DropdownMenuItem
|
|
602
|
-
classes={{
|
|
603
|
-
root: "text-green-200 hover:bg-green-500/20 focus:bg-green-500/20",
|
|
604
|
-
}}
|
|
605
|
-
>
|
|
606
|
-
<AudioBarIcon className="h-4 w-4" />
|
|
607
|
-
Success Action
|
|
608
|
-
</DropdownMenuItem>
|
|
609
|
-
</DropdownMenuGroup>
|
|
610
|
-
</DropdownMenuContent>
|
|
611
|
-
</DropdownMenu>
|
|
612
|
-
|
|
613
|
-
{/* Purple Theme */}
|
|
614
|
-
<DropdownMenu>
|
|
615
|
-
<DropdownMenuTrigger asChild>
|
|
616
|
-
<Button>Purple Theme</Button>
|
|
617
|
-
</DropdownMenuTrigger>
|
|
618
|
-
<DropdownMenuContent
|
|
619
|
-
classes={{
|
|
620
|
-
root: "bg-purple-900/40 border-purple-500/20",
|
|
621
|
-
border: "bg-gradient-to-r from-purple-500 to-pink-500",
|
|
622
|
-
}}
|
|
623
|
-
>
|
|
624
|
-
<DropdownMenuGroup>
|
|
625
|
-
<DropdownMenuItem
|
|
626
|
-
classes={{
|
|
627
|
-
root: "text-purple-200 hover:bg-purple-500/20 focus:bg-purple-500/20",
|
|
628
|
-
}}
|
|
629
|
-
>
|
|
630
|
-
<TickIcon className="h-4 w-4" />
|
|
631
|
-
Purple Item
|
|
632
|
-
</DropdownMenuItem>
|
|
633
|
-
<DropdownMenuItem
|
|
634
|
-
classes={{
|
|
635
|
-
root: "text-purple-200 hover:bg-purple-500/20 focus:bg-purple-500/20",
|
|
636
|
-
}}
|
|
637
|
-
>
|
|
638
|
-
<AudioBarIcon className="h-4 w-4" />
|
|
639
|
-
Creative Action
|
|
640
|
-
</DropdownMenuItem>
|
|
641
|
-
</DropdownMenuGroup>
|
|
642
|
-
</DropdownMenuContent>
|
|
643
|
-
</DropdownMenu>
|
|
644
164
|
</div>
|
|
645
|
-
</div>
|
|
646
|
-
),
|
|
647
|
-
parameters: {
|
|
648
|
-
docs: {
|
|
649
|
-
description: {
|
|
650
|
-
story:
|
|
651
|
-
"Custom styled dropdown menus using the classes prop for theme variations with logical grouping.",
|
|
652
|
-
},
|
|
653
|
-
},
|
|
654
|
-
},
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// 6. Complex Menu Example
|
|
658
|
-
export const ComplexMenu: Story = {
|
|
659
|
-
render: () => {
|
|
660
|
-
const [bookmarked, setBookmarked] = useState(false)
|
|
661
|
-
const [notifications, setNotifications] = useState(true)
|
|
662
|
-
const [viewMode, setViewMode] = useState("grid")
|
|
663
165
|
|
|
664
|
-
|
|
665
|
-
<div className="space-y-
|
|
666
|
-
<
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
grouping
|
|
671
|
-
</p>
|
|
672
|
-
</div>
|
|
673
|
-
|
|
674
|
-
<div className="flex justify-center">
|
|
166
|
+
{/* Group + separator */}
|
|
167
|
+
<div className="space-y-3">
|
|
168
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
169
|
+
Groups & Separators
|
|
170
|
+
</h4>
|
|
171
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
675
172
|
<DropdownMenu>
|
|
676
173
|
<DropdownMenuTrigger asChild>
|
|
677
|
-
<Button
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
174
|
+
<Button
|
|
175
|
+
variant="outline"
|
|
176
|
+
innerClassName="flex items-center gap-2"
|
|
177
|
+
>
|
|
178
|
+
Grouped
|
|
179
|
+
<ChevronDownIcon className="size-4" />
|
|
681
180
|
</Button>
|
|
682
181
|
</DropdownMenuTrigger>
|
|
683
|
-
<DropdownMenuContent className="w-
|
|
684
|
-
|
|
685
|
-
<DropdownMenuLabel>Quick Actions</DropdownMenuLabel>
|
|
182
|
+
<DropdownMenuContent className="w-52">
|
|
183
|
+
<DropdownMenuLabel>File</DropdownMenuLabel>
|
|
686
184
|
<DropdownMenuSeparator />
|
|
687
185
|
<DropdownMenuGroup>
|
|
688
186
|
<DropdownMenuItem>
|
|
689
|
-
<
|
|
690
|
-
|
|
691
|
-
<DropdownMenuShortcut>⌘
|
|
187
|
+
<FileTextIcon />
|
|
188
|
+
New
|
|
189
|
+
<DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
|
|
692
190
|
</DropdownMenuItem>
|
|
693
191
|
<DropdownMenuItem>
|
|
694
|
-
<
|
|
695
|
-
|
|
696
|
-
<DropdownMenuShortcut>⌘
|
|
192
|
+
<UploadIcon />
|
|
193
|
+
Upload
|
|
194
|
+
<DropdownMenuShortcut>⌘U</DropdownMenuShortcut>
|
|
697
195
|
</DropdownMenuItem>
|
|
196
|
+
</DropdownMenuGroup>
|
|
197
|
+
<DropdownMenuSeparator />
|
|
198
|
+
<DropdownMenuLabel>Edit</DropdownMenuLabel>
|
|
199
|
+
<DropdownMenuSeparator />
|
|
200
|
+
<DropdownMenuGroup>
|
|
698
201
|
<DropdownMenuItem>
|
|
699
|
-
<
|
|
700
|
-
|
|
701
|
-
<DropdownMenuShortcut
|
|
202
|
+
<EditBigIcon />
|
|
203
|
+
Rename
|
|
204
|
+
<DropdownMenuShortcut>⌘R</DropdownMenuShortcut>
|
|
205
|
+
</DropdownMenuItem>
|
|
206
|
+
<DropdownMenuItem>
|
|
207
|
+
<DownloadIcon />
|
|
208
|
+
Download
|
|
209
|
+
<DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
|
|
702
210
|
</DropdownMenuItem>
|
|
703
211
|
</DropdownMenuGroup>
|
|
212
|
+
</DropdownMenuContent>
|
|
213
|
+
</DropdownMenu>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
704
216
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
217
|
+
{/* Checkbox items */}
|
|
218
|
+
<div className="space-y-3">
|
|
219
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
220
|
+
Checkbox Items
|
|
221
|
+
</h4>
|
|
222
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
223
|
+
<DropdownMenu>
|
|
224
|
+
<DropdownMenuTrigger asChild>
|
|
225
|
+
<Button
|
|
226
|
+
variant="outline"
|
|
227
|
+
innerClassName="flex items-center gap-2"
|
|
228
|
+
>
|
|
229
|
+
Preferences
|
|
230
|
+
<ChevronDownIcon className="size-4" />
|
|
231
|
+
</Button>
|
|
232
|
+
</DropdownMenuTrigger>
|
|
233
|
+
<DropdownMenuContent>
|
|
234
|
+
<DropdownMenuLabel>Display</DropdownMenuLabel>
|
|
709
235
|
<DropdownMenuSeparator />
|
|
710
236
|
<DropdownMenuGroup>
|
|
711
|
-
<DropdownMenuCheckboxItem
|
|
712
|
-
|
|
713
|
-
onCheckedChange={setBookmarked}
|
|
714
|
-
>
|
|
715
|
-
<TickIcon className="h-4 w-4" />
|
|
716
|
-
Bookmark
|
|
237
|
+
<DropdownMenuCheckboxItem checked>
|
|
238
|
+
Show artwork
|
|
717
239
|
</DropdownMenuCheckboxItem>
|
|
718
|
-
<DropdownMenuCheckboxItem
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
>
|
|
722
|
-
|
|
723
|
-
Enable Notifications
|
|
240
|
+
<DropdownMenuCheckboxItem checked={false}>
|
|
241
|
+
Show lyrics
|
|
242
|
+
</DropdownMenuCheckboxItem>
|
|
243
|
+
<DropdownMenuCheckboxItem checked>
|
|
244
|
+
Show queue
|
|
724
245
|
</DropdownMenuCheckboxItem>
|
|
725
246
|
</DropdownMenuGroup>
|
|
247
|
+
</DropdownMenuContent>
|
|
248
|
+
</DropdownMenu>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
726
251
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
252
|
+
{/* Radio items */}
|
|
253
|
+
<div className="space-y-3">
|
|
254
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
255
|
+
Radio Items
|
|
256
|
+
</h4>
|
|
257
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
258
|
+
<DropdownMenu>
|
|
259
|
+
<DropdownMenuTrigger asChild>
|
|
260
|
+
<Button
|
|
261
|
+
variant="outline"
|
|
262
|
+
innerClassName="flex items-center gap-2"
|
|
263
|
+
>
|
|
264
|
+
Sort by
|
|
265
|
+
<AngleDownIcon className="size-4" />
|
|
266
|
+
</Button>
|
|
267
|
+
</DropdownMenuTrigger>
|
|
268
|
+
<DropdownMenuContent>
|
|
269
|
+
<DropdownMenuLabel>Sort Order</DropdownMenuLabel>
|
|
731
270
|
<DropdownMenuSeparator />
|
|
732
271
|
<DropdownMenuGroup>
|
|
733
|
-
<DropdownMenuRadioGroup
|
|
734
|
-
value=
|
|
735
|
-
|
|
736
|
-
>
|
|
737
|
-
<DropdownMenuRadioItem value="grid">
|
|
738
|
-
Grid View
|
|
272
|
+
<DropdownMenuRadioGroup value="recent">
|
|
273
|
+
<DropdownMenuRadioItem value="recent">
|
|
274
|
+
Most Recent
|
|
739
275
|
</DropdownMenuRadioItem>
|
|
740
|
-
<DropdownMenuRadioItem value="
|
|
741
|
-
|
|
276
|
+
<DropdownMenuRadioItem value="alpha">
|
|
277
|
+
Alphabetical
|
|
742
278
|
</DropdownMenuRadioItem>
|
|
743
|
-
<DropdownMenuRadioItem value="
|
|
744
|
-
|
|
279
|
+
<DropdownMenuRadioItem value="plays">
|
|
280
|
+
Most Played
|
|
745
281
|
</DropdownMenuRadioItem>
|
|
746
282
|
</DropdownMenuRadioGroup>
|
|
747
283
|
</DropdownMenuGroup>
|
|
284
|
+
</DropdownMenuContent>
|
|
285
|
+
</DropdownMenu>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
748
288
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
289
|
+
{/* Sub-menus */}
|
|
290
|
+
<div className="space-y-3">
|
|
291
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
292
|
+
Nested Sub-menu
|
|
293
|
+
</h4>
|
|
294
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
295
|
+
<DropdownMenu>
|
|
296
|
+
<DropdownMenuTrigger asChild>
|
|
297
|
+
<Button
|
|
298
|
+
variant="outline"
|
|
299
|
+
innerClassName="flex items-center gap-2"
|
|
300
|
+
>
|
|
301
|
+
<PlusIcon className="size-4" />
|
|
302
|
+
Add to…
|
|
303
|
+
</Button>
|
|
304
|
+
</DropdownMenuTrigger>
|
|
305
|
+
<DropdownMenuContent>
|
|
752
306
|
<DropdownMenuGroup>
|
|
753
307
|
<DropdownMenuSub>
|
|
754
308
|
<DropdownMenuSubTrigger>
|
|
755
|
-
<
|
|
756
|
-
|
|
309
|
+
<AudioBarIcon />
|
|
310
|
+
Playlist
|
|
757
311
|
</DropdownMenuSubTrigger>
|
|
758
312
|
<DropdownMenuSubContent>
|
|
759
313
|
<DropdownMenuGroup>
|
|
760
314
|
<DropdownMenuItem>
|
|
761
|
-
<
|
|
762
|
-
|
|
315
|
+
<MusicalNoteIcon />
|
|
316
|
+
Late Night Drive
|
|
763
317
|
</DropdownMenuItem>
|
|
764
318
|
<DropdownMenuItem>
|
|
765
|
-
<
|
|
766
|
-
|
|
319
|
+
<MusicalNoteIcon />
|
|
320
|
+
Focus Mode
|
|
767
321
|
</DropdownMenuItem>
|
|
768
322
|
<DropdownMenuItem>
|
|
769
|
-
<
|
|
770
|
-
|
|
323
|
+
<MusicalNoteIcon />
|
|
324
|
+
Morning Energy
|
|
771
325
|
</DropdownMenuItem>
|
|
772
326
|
</DropdownMenuGroup>
|
|
773
327
|
<DropdownMenuSeparator />
|
|
774
328
|
<DropdownMenuGroup>
|
|
775
329
|
<DropdownMenuItem>
|
|
776
|
-
<PlusIcon
|
|
777
|
-
|
|
330
|
+
<PlusIcon />
|
|
331
|
+
New Playlist…
|
|
778
332
|
</DropdownMenuItem>
|
|
779
333
|
</DropdownMenuGroup>
|
|
780
334
|
</DropdownMenuSubContent>
|
|
781
335
|
</DropdownMenuSub>
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
{/* Danger Group */}
|
|
787
|
-
<DropdownMenuGroup>
|
|
788
|
-
<DropdownMenuItem variant="destructive">
|
|
789
|
-
<TrashIcon className="h-4 w-4" />
|
|
790
|
-
Delete Item
|
|
791
|
-
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
|
336
|
+
<DropdownMenuItem>
|
|
337
|
+
<AudioBarIcon />
|
|
338
|
+
Queue
|
|
339
|
+
<DropdownMenuShortcut>⌘Q</DropdownMenuShortcut>
|
|
792
340
|
</DropdownMenuItem>
|
|
793
341
|
</DropdownMenuGroup>
|
|
794
342
|
</DropdownMenuContent>
|
|
795
343
|
</DropdownMenu>
|
|
796
344
|
</div>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
),
|
|
348
|
+
parameters: {
|
|
349
|
+
docs: {
|
|
350
|
+
description: {
|
|
351
|
+
story:
|
|
352
|
+
"All item type configurations displayed in separate labeled groups: basic items with keyboard shortcuts, inset items, group+separator layouts, checkbox items, radio items, and a nested sub-menu trigger. Each section can be opened independently to inspect how that item type renders.",
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ─── Interactive ──────────────────────────────────────────────────────────────
|
|
359
|
+
|
|
360
|
+
export const Interactive: Story = {
|
|
361
|
+
render: () => {
|
|
362
|
+
const [showArtwork, setShowArtwork] = useState(true)
|
|
363
|
+
const [showLyrics, setShowLyrics] = useState(false)
|
|
364
|
+
const [showQueue, setShowQueue] = useState(true)
|
|
365
|
+
const [audioQuality, setAudioQuality] = useState("high")
|
|
366
|
+
const [sortOrder, setSortOrder] = useState("recent")
|
|
367
|
+
const [lastAction, setLastAction] = useState<string | null>(null)
|
|
368
|
+
|
|
369
|
+
const qualityLabels: Record<string, string> = {
|
|
370
|
+
low: "Normal (96 kbps)",
|
|
371
|
+
high: "High (320 kbps)",
|
|
372
|
+
lossless: "Lossless (FLAC)",
|
|
373
|
+
}
|
|
374
|
+
const sortLabels: Record<string, string> = {
|
|
375
|
+
recent: "Most Recent",
|
|
376
|
+
alpha: "Alphabetical",
|
|
377
|
+
plays: "Most Played",
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
<div className="w-full p-8">
|
|
382
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
383
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
384
|
+
{/* Controls panel */}
|
|
385
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
386
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
387
|
+
Live State
|
|
388
|
+
</p>
|
|
389
|
+
|
|
390
|
+
<div className="space-y-2">
|
|
391
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
392
|
+
Display Toggles
|
|
393
|
+
</p>
|
|
394
|
+
<div className="space-y-1">
|
|
395
|
+
{[
|
|
396
|
+
{ label: "Artwork", value: showArtwork },
|
|
397
|
+
{ label: "Lyrics", value: showLyrics },
|
|
398
|
+
{ label: "Queue", value: showQueue },
|
|
399
|
+
].map(({ label, value }) => (
|
|
400
|
+
<div key={label} className="flex justify-between">
|
|
401
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
402
|
+
{label}
|
|
403
|
+
</span>
|
|
404
|
+
<span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm font-medium">
|
|
405
|
+
{value ? "On" : "Off"}
|
|
406
|
+
</span>
|
|
407
|
+
</div>
|
|
408
|
+
))}
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
413
|
+
|
|
414
|
+
<div className="space-y-1">
|
|
415
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
416
|
+
Audio Quality
|
|
417
|
+
</p>
|
|
418
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
419
|
+
{qualityLabels[audioQuality]}
|
|
420
|
+
</p>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div className="space-y-1">
|
|
424
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
425
|
+
Sort Order
|
|
426
|
+
</p>
|
|
427
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
428
|
+
{sortLabels[sortOrder]}
|
|
429
|
+
</p>
|
|
430
|
+
</div>
|
|
431
|
+
|
|
432
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
433
|
+
|
|
434
|
+
<div className="space-y-1">
|
|
435
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
436
|
+
Last Action
|
|
437
|
+
</p>
|
|
438
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md truncate font-medium">
|
|
439
|
+
{lastAction ?? "—"}
|
|
440
|
+
</p>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
797
443
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
444
|
+
{/* Preview stage */}
|
|
445
|
+
<div className="flex flex-col gap-4 lg:col-span-2">
|
|
446
|
+
<div className="flex flex-wrap justify-center gap-4">
|
|
447
|
+
{/* Checkbox preferences */}
|
|
448
|
+
<DropdownMenu>
|
|
449
|
+
<DropdownMenuTrigger asChild>
|
|
450
|
+
<Button
|
|
451
|
+
variant="outline"
|
|
452
|
+
innerClassName="flex items-center gap-2"
|
|
453
|
+
>
|
|
454
|
+
Display
|
|
455
|
+
<ChevronDownIcon className="size-4" />
|
|
456
|
+
</Button>
|
|
457
|
+
</DropdownMenuTrigger>
|
|
458
|
+
<DropdownMenuContent>
|
|
459
|
+
<DropdownMenuLabel>Display Options</DropdownMenuLabel>
|
|
460
|
+
<DropdownMenuSeparator />
|
|
461
|
+
<DropdownMenuGroup>
|
|
462
|
+
<DropdownMenuCheckboxItem
|
|
463
|
+
checked={showArtwork}
|
|
464
|
+
onCheckedChange={(v) => {
|
|
465
|
+
setShowArtwork(v)
|
|
466
|
+
setLastAction(`Show Artwork → ${v ? "On" : "Off"}`)
|
|
467
|
+
}}
|
|
468
|
+
>
|
|
469
|
+
Show Artwork
|
|
470
|
+
</DropdownMenuCheckboxItem>
|
|
471
|
+
<DropdownMenuCheckboxItem
|
|
472
|
+
checked={showLyrics}
|
|
473
|
+
onCheckedChange={(v) => {
|
|
474
|
+
setShowLyrics(v)
|
|
475
|
+
setLastAction(`Show Lyrics → ${v ? "On" : "Off"}`)
|
|
476
|
+
}}
|
|
477
|
+
>
|
|
478
|
+
Show Lyrics
|
|
479
|
+
</DropdownMenuCheckboxItem>
|
|
480
|
+
<DropdownMenuCheckboxItem
|
|
481
|
+
checked={showQueue}
|
|
482
|
+
onCheckedChange={(v) => {
|
|
483
|
+
setShowQueue(v)
|
|
484
|
+
setLastAction(`Show Queue → ${v ? "On" : "Off"}`)
|
|
485
|
+
}}
|
|
486
|
+
>
|
|
487
|
+
Show Queue
|
|
488
|
+
</DropdownMenuCheckboxItem>
|
|
489
|
+
</DropdownMenuGroup>
|
|
490
|
+
</DropdownMenuContent>
|
|
491
|
+
</DropdownMenu>
|
|
492
|
+
|
|
493
|
+
{/* Radio — audio quality */}
|
|
494
|
+
<DropdownMenu>
|
|
495
|
+
<DropdownMenuTrigger asChild>
|
|
496
|
+
<Button
|
|
497
|
+
variant="outline"
|
|
498
|
+
innerClassName="flex items-center gap-2"
|
|
499
|
+
>
|
|
500
|
+
Quality: {qualityLabels[audioQuality].split(" ")[0]}
|
|
501
|
+
<AngleDownIcon className="size-4" />
|
|
502
|
+
</Button>
|
|
503
|
+
</DropdownMenuTrigger>
|
|
504
|
+
<DropdownMenuContent>
|
|
505
|
+
<DropdownMenuLabel>Audio Quality</DropdownMenuLabel>
|
|
506
|
+
<DropdownMenuSeparator />
|
|
507
|
+
<DropdownMenuGroup>
|
|
508
|
+
<DropdownMenuRadioGroup
|
|
509
|
+
value={audioQuality}
|
|
510
|
+
onValueChange={(v) => {
|
|
511
|
+
setAudioQuality(v)
|
|
512
|
+
setLastAction(`Quality → ${qualityLabels[v]}`)
|
|
513
|
+
}}
|
|
514
|
+
>
|
|
515
|
+
<DropdownMenuRadioItem value="low">
|
|
516
|
+
Normal (96 kbps)
|
|
517
|
+
</DropdownMenuRadioItem>
|
|
518
|
+
<DropdownMenuRadioItem value="high">
|
|
519
|
+
High (320 kbps)
|
|
520
|
+
</DropdownMenuRadioItem>
|
|
521
|
+
<DropdownMenuRadioItem value="lossless">
|
|
522
|
+
Lossless (FLAC)
|
|
523
|
+
</DropdownMenuRadioItem>
|
|
524
|
+
</DropdownMenuRadioGroup>
|
|
525
|
+
</DropdownMenuGroup>
|
|
526
|
+
</DropdownMenuContent>
|
|
527
|
+
</DropdownMenu>
|
|
528
|
+
|
|
529
|
+
{/* Radio — sort order */}
|
|
530
|
+
<DropdownMenu>
|
|
531
|
+
<DropdownMenuTrigger asChild>
|
|
532
|
+
<Button
|
|
533
|
+
variant="outline"
|
|
534
|
+
innerClassName="flex items-center gap-2"
|
|
535
|
+
>
|
|
536
|
+
Sort
|
|
537
|
+
<AngleDownIcon className="size-4" />
|
|
538
|
+
</Button>
|
|
539
|
+
</DropdownMenuTrigger>
|
|
540
|
+
<DropdownMenuContent>
|
|
541
|
+
<DropdownMenuLabel>Sort Library By</DropdownMenuLabel>
|
|
542
|
+
<DropdownMenuSeparator />
|
|
543
|
+
<DropdownMenuGroup>
|
|
544
|
+
<DropdownMenuRadioGroup
|
|
545
|
+
value={sortOrder}
|
|
546
|
+
onValueChange={(v) => {
|
|
547
|
+
setSortOrder(v)
|
|
548
|
+
setLastAction(`Sort → ${sortLabels[v]}`)
|
|
549
|
+
}}
|
|
550
|
+
>
|
|
551
|
+
<DropdownMenuRadioItem value="recent">
|
|
552
|
+
Most Recent
|
|
553
|
+
</DropdownMenuRadioItem>
|
|
554
|
+
<DropdownMenuRadioItem value="alpha">
|
|
555
|
+
Alphabetical
|
|
556
|
+
</DropdownMenuRadioItem>
|
|
557
|
+
<DropdownMenuRadioItem value="plays">
|
|
558
|
+
Most Played
|
|
559
|
+
</DropdownMenuRadioItem>
|
|
560
|
+
</DropdownMenuRadioGroup>
|
|
561
|
+
</DropdownMenuGroup>
|
|
562
|
+
</DropdownMenuContent>
|
|
563
|
+
</DropdownMenu>
|
|
564
|
+
</div>
|
|
565
|
+
|
|
566
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
567
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
568
|
+
Checkbox and radio selections update state immediately — open
|
|
569
|
+
the left panel to see live values.
|
|
570
|
+
</code>
|
|
571
|
+
</div>
|
|
808
572
|
</div>
|
|
809
573
|
</div>
|
|
810
574
|
</div>
|
|
@@ -815,405 +579,256 @@ export const ComplexMenu: Story = {
|
|
|
815
579
|
docs: {
|
|
816
580
|
description: {
|
|
817
581
|
story:
|
|
818
|
-
"
|
|
582
|
+
"Stateful dropdown story demonstrating live checkbox and radio item selection. Three separate menus manage display toggle preferences, audio quality (radio single-select), and library sort order (radio single-select). The left panel reflects every state change in real time so the interaction loop is visible without opening browser DevTools.",
|
|
819
583
|
},
|
|
820
584
|
},
|
|
821
585
|
},
|
|
822
586
|
}
|
|
823
587
|
|
|
824
|
-
//
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
<h3 className="text-fm-primary mb-2 font-medium">
|
|
830
|
-
Positioning Examples
|
|
831
|
-
</h3>
|
|
832
|
-
<p className="text-fm-secondary text-sm">
|
|
833
|
-
Different positioning and alignment options with grouped content
|
|
834
|
-
</p>
|
|
835
|
-
</div>
|
|
588
|
+
// ─── UseCases ─────────────────────────────────────────────────────────────────
|
|
589
|
+
|
|
590
|
+
export const UseCases: Story = {
|
|
591
|
+
render: () => {
|
|
592
|
+
const [liked, setLiked] = useState(false)
|
|
836
593
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
594
|
+
return (
|
|
595
|
+
<div className="mx-auto max-w-3xl space-y-8 p-8">
|
|
596
|
+
{/* 1 — Track action menu */}
|
|
597
|
+
<div className="space-y-3">
|
|
598
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
599
|
+
Track Action Menu
|
|
842
600
|
</h4>
|
|
843
|
-
<div className="flex
|
|
601
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center justify-between rounded-xl border p-4">
|
|
602
|
+
<div className="flex items-center gap-3">
|
|
603
|
+
<div className="bg-fm-surface-tertiary size-10 shrink-0 rounded-lg" />
|
|
604
|
+
<div className="space-y-0.5">
|
|
605
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
606
|
+
Midnight Echoes
|
|
607
|
+
</p>
|
|
608
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
609
|
+
Luna Vex · 4:12
|
|
610
|
+
</p>
|
|
611
|
+
</div>
|
|
612
|
+
</div>
|
|
844
613
|
<DropdownMenu>
|
|
845
614
|
<DropdownMenuTrigger asChild>
|
|
846
|
-
<Button variant="
|
|
847
|
-
|
|
615
|
+
<Button variant="text" size="sm">
|
|
616
|
+
<VerticalMenuIcon />
|
|
848
617
|
</Button>
|
|
849
618
|
</DropdownMenuTrigger>
|
|
850
|
-
<DropdownMenuContent align="
|
|
619
|
+
<DropdownMenuContent align="end" className="w-52">
|
|
851
620
|
<DropdownMenuGroup>
|
|
852
|
-
<DropdownMenuItem>
|
|
853
|
-
|
|
621
|
+
<DropdownMenuItem>
|
|
622
|
+
<AudioBarIcon />
|
|
623
|
+
Add to Queue
|
|
624
|
+
<DropdownMenuShortcut>⌘Q</DropdownMenuShortcut>
|
|
625
|
+
</DropdownMenuItem>
|
|
626
|
+
<DropdownMenuItem onSelect={() => setLiked((v) => !v)}>
|
|
627
|
+
<HeartIcon />
|
|
628
|
+
{liked ? "Unlike Track" : "Like Track"}
|
|
629
|
+
<DropdownMenuShortcut>⌘L</DropdownMenuShortcut>
|
|
630
|
+
</DropdownMenuItem>
|
|
854
631
|
</DropdownMenuGroup>
|
|
855
|
-
|
|
856
|
-
</DropdownMenu>
|
|
857
|
-
|
|
858
|
-
<DropdownMenu>
|
|
859
|
-
<DropdownMenuTrigger asChild>
|
|
860
|
-
<Button variant="outline" size="sm">
|
|
861
|
-
Align Center
|
|
862
|
-
</Button>
|
|
863
|
-
</DropdownMenuTrigger>
|
|
864
|
-
<DropdownMenuContent align="center">
|
|
632
|
+
<DropdownMenuSeparator />
|
|
865
633
|
<DropdownMenuGroup>
|
|
866
|
-
<
|
|
867
|
-
|
|
634
|
+
<DropdownMenuSub>
|
|
635
|
+
<DropdownMenuSubTrigger>
|
|
636
|
+
<MusicalNoteIcon />
|
|
637
|
+
Add to Playlist
|
|
638
|
+
</DropdownMenuSubTrigger>
|
|
639
|
+
<DropdownMenuSubContent>
|
|
640
|
+
<DropdownMenuGroup>
|
|
641
|
+
<DropdownMenuItem>
|
|
642
|
+
<CircleTickIcon />
|
|
643
|
+
Late Night Drive
|
|
644
|
+
</DropdownMenuItem>
|
|
645
|
+
<DropdownMenuItem>
|
|
646
|
+
<CircleTickIcon />
|
|
647
|
+
Focus Mode
|
|
648
|
+
</DropdownMenuItem>
|
|
649
|
+
<DropdownMenuItem>
|
|
650
|
+
<CircleTickIcon />
|
|
651
|
+
Morning Energy
|
|
652
|
+
</DropdownMenuItem>
|
|
653
|
+
</DropdownMenuGroup>
|
|
654
|
+
<DropdownMenuSeparator />
|
|
655
|
+
<DropdownMenuGroup>
|
|
656
|
+
<DropdownMenuItem>
|
|
657
|
+
<PlusIcon />
|
|
658
|
+
New Playlist…
|
|
659
|
+
</DropdownMenuItem>
|
|
660
|
+
</DropdownMenuGroup>
|
|
661
|
+
</DropdownMenuSubContent>
|
|
662
|
+
</DropdownMenuSub>
|
|
663
|
+
<DropdownMenuItem>
|
|
664
|
+
<ShareIcon />
|
|
665
|
+
Share Track
|
|
666
|
+
<DropdownMenuShortcut>⌘⇧S</DropdownMenuShortcut>
|
|
667
|
+
</DropdownMenuItem>
|
|
668
|
+
<DropdownMenuItem>
|
|
669
|
+
<DownloadIcon />
|
|
670
|
+
Download Offline
|
|
671
|
+
<DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
|
|
672
|
+
</DropdownMenuItem>
|
|
868
673
|
</DropdownMenuGroup>
|
|
869
|
-
|
|
870
|
-
</DropdownMenu>
|
|
871
|
-
|
|
872
|
-
<DropdownMenu>
|
|
873
|
-
<DropdownMenuTrigger asChild>
|
|
874
|
-
<Button variant="outline" size="sm">
|
|
875
|
-
Align End
|
|
876
|
-
</Button>
|
|
877
|
-
</DropdownMenuTrigger>
|
|
878
|
-
<DropdownMenuContent align="end">
|
|
674
|
+
<DropdownMenuSeparator />
|
|
879
675
|
<DropdownMenuGroup>
|
|
880
|
-
<DropdownMenuItem
|
|
881
|
-
|
|
676
|
+
<DropdownMenuItem variant="destructive">
|
|
677
|
+
<TrashIcon />
|
|
678
|
+
Remove from Library
|
|
679
|
+
</DropdownMenuItem>
|
|
882
680
|
</DropdownMenuGroup>
|
|
883
681
|
</DropdownMenuContent>
|
|
884
682
|
</DropdownMenu>
|
|
885
683
|
</div>
|
|
684
|
+
{liked && (
|
|
685
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm text-center">
|
|
686
|
+
Track liked — heart state toggles via the menu above.
|
|
687
|
+
</p>
|
|
688
|
+
)}
|
|
886
689
|
</div>
|
|
887
690
|
|
|
888
|
-
{/*
|
|
889
|
-
<div className="space-y-
|
|
890
|
-
<h4 className="text-fm-secondary text-
|
|
891
|
-
|
|
691
|
+
{/* 2 — User account menu */}
|
|
692
|
+
<div className="space-y-3">
|
|
693
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
694
|
+
User Account Menu
|
|
695
|
+
</h4>
|
|
696
|
+
<div className="flex justify-center">
|
|
892
697
|
<DropdownMenu>
|
|
893
698
|
<DropdownMenuTrigger asChild>
|
|
894
|
-
<Button
|
|
895
|
-
|
|
699
|
+
<Button
|
|
700
|
+
variant="outline"
|
|
701
|
+
innerClassName="flex items-center gap-2"
|
|
702
|
+
>
|
|
703
|
+
<div className="bg-fm-surface-tertiary size-6 rounded-full" />
|
|
704
|
+
Alex Rivera
|
|
705
|
+
<ChevronDownIcon className="size-4" />
|
|
896
706
|
</Button>
|
|
897
707
|
</DropdownMenuTrigger>
|
|
898
|
-
<DropdownMenuContent
|
|
708
|
+
<DropdownMenuContent align="end" className="w-52">
|
|
709
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
710
|
+
<DropdownMenuSeparator />
|
|
899
711
|
<DropdownMenuGroup>
|
|
900
|
-
<DropdownMenuItem>
|
|
901
|
-
|
|
712
|
+
<DropdownMenuItem>
|
|
713
|
+
<EyeOpenIcon />
|
|
714
|
+
View Profile
|
|
715
|
+
<DropdownMenuShortcut>⌘P</DropdownMenuShortcut>
|
|
716
|
+
</DropdownMenuItem>
|
|
717
|
+
<DropdownMenuItem>
|
|
718
|
+
<StarIcon />
|
|
719
|
+
Subscription
|
|
720
|
+
</DropdownMenuItem>
|
|
721
|
+
<DropdownMenuItem>
|
|
722
|
+
<MaintenanceIcon />
|
|
723
|
+
Settings
|
|
724
|
+
<DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
|
|
725
|
+
</DropdownMenuItem>
|
|
902
726
|
</DropdownMenuGroup>
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
</DropdownMenuTrigger>
|
|
912
|
-
<DropdownMenuContent>
|
|
727
|
+
<DropdownMenuSeparator />
|
|
728
|
+
<DropdownMenuGroup>
|
|
729
|
+
<DropdownMenuItem>
|
|
730
|
+
<SearchIcon />
|
|
731
|
+
Help & Support
|
|
732
|
+
</DropdownMenuItem>
|
|
733
|
+
</DropdownMenuGroup>
|
|
734
|
+
<DropdownMenuSeparator />
|
|
913
735
|
<DropdownMenuGroup>
|
|
914
|
-
<DropdownMenuItem
|
|
915
|
-
|
|
736
|
+
<DropdownMenuItem variant="destructive">
|
|
737
|
+
Log Out
|
|
738
|
+
<DropdownMenuShortcut>⌘⇧Q</DropdownMenuShortcut>
|
|
739
|
+
</DropdownMenuItem>
|
|
916
740
|
</DropdownMenuGroup>
|
|
917
741
|
</DropdownMenuContent>
|
|
918
742
|
</DropdownMenu>
|
|
743
|
+
</div>
|
|
744
|
+
</div>
|
|
919
745
|
|
|
746
|
+
{/* 3 — Settings context menu */}
|
|
747
|
+
<div className="space-y-3">
|
|
748
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
749
|
+
Settings Context Menu
|
|
750
|
+
</h4>
|
|
751
|
+
<div className="flex justify-center">
|
|
920
752
|
<DropdownMenu>
|
|
921
753
|
<DropdownMenuTrigger asChild>
|
|
922
|
-
<Button
|
|
923
|
-
|
|
754
|
+
<Button
|
|
755
|
+
variant="outline"
|
|
756
|
+
innerClassName="flex items-center gap-2"
|
|
757
|
+
>
|
|
758
|
+
<MaintenanceIcon className="size-4" />
|
|
759
|
+
Settings
|
|
760
|
+
<AngleDownIcon className="size-4" />
|
|
924
761
|
</Button>
|
|
925
762
|
</DropdownMenuTrigger>
|
|
926
|
-
<DropdownMenuContent
|
|
763
|
+
<DropdownMenuContent className="w-56">
|
|
764
|
+
<DropdownMenuLabel>Application</DropdownMenuLabel>
|
|
765
|
+
<DropdownMenuSeparator />
|
|
766
|
+
<DropdownMenuGroup>
|
|
767
|
+
<DropdownMenuSub>
|
|
768
|
+
<DropdownMenuSubTrigger>
|
|
769
|
+
<AudioBarIcon />
|
|
770
|
+
Audio Settings
|
|
771
|
+
</DropdownMenuSubTrigger>
|
|
772
|
+
<DropdownMenuSubContent>
|
|
773
|
+
<DropdownMenuGroup>
|
|
774
|
+
<DropdownMenuItem>
|
|
775
|
+
Equaliser
|
|
776
|
+
<DropdownMenuShortcut>⌘E</DropdownMenuShortcut>
|
|
777
|
+
</DropdownMenuItem>
|
|
778
|
+
<DropdownMenuItem>Crossfade</DropdownMenuItem>
|
|
779
|
+
<DropdownMenuItem>Normalisation</DropdownMenuItem>
|
|
780
|
+
</DropdownMenuGroup>
|
|
781
|
+
</DropdownMenuSubContent>
|
|
782
|
+
</DropdownMenuSub>
|
|
783
|
+
<DropdownMenuSub>
|
|
784
|
+
<DropdownMenuSubTrigger>
|
|
785
|
+
<MusicalNoteIcon />
|
|
786
|
+
Library Settings
|
|
787
|
+
</DropdownMenuSubTrigger>
|
|
788
|
+
<DropdownMenuSubContent>
|
|
789
|
+
<DropdownMenuGroup>
|
|
790
|
+
<DropdownMenuItem>
|
|
791
|
+
<UploadIcon />
|
|
792
|
+
Import Music
|
|
793
|
+
</DropdownMenuItem>
|
|
794
|
+
<DropdownMenuItem>
|
|
795
|
+
<EditBigIcon />
|
|
796
|
+
Manage Storage
|
|
797
|
+
</DropdownMenuItem>
|
|
798
|
+
</DropdownMenuGroup>
|
|
799
|
+
</DropdownMenuSubContent>
|
|
800
|
+
</DropdownMenuSub>
|
|
801
|
+
</DropdownMenuGroup>
|
|
802
|
+
<DropdownMenuSeparator />
|
|
927
803
|
<DropdownMenuGroup>
|
|
928
|
-
<DropdownMenuItem>
|
|
929
|
-
|
|
804
|
+
<DropdownMenuItem>
|
|
805
|
+
<FileTextIcon />
|
|
806
|
+
Privacy Policy
|
|
807
|
+
</DropdownMenuItem>
|
|
808
|
+
<DropdownMenuItem>
|
|
809
|
+
<ShareIcon />
|
|
810
|
+
Terms of Service
|
|
811
|
+
</DropdownMenuItem>
|
|
812
|
+
</DropdownMenuGroup>
|
|
813
|
+
<DropdownMenuSeparator />
|
|
814
|
+
<DropdownMenuGroup>
|
|
815
|
+
<DropdownMenuItem variant="destructive">
|
|
816
|
+
<TrashIcon />
|
|
817
|
+
Reset All Settings
|
|
818
|
+
</DropdownMenuItem>
|
|
930
819
|
</DropdownMenuGroup>
|
|
931
820
|
</DropdownMenuContent>
|
|
932
821
|
</DropdownMenu>
|
|
933
822
|
</div>
|
|
934
823
|
</div>
|
|
935
824
|
</div>
|
|
936
|
-
|
|
937
|
-
),
|
|
938
|
-
parameters: {
|
|
939
|
-
docs: {
|
|
940
|
-
description: {
|
|
941
|
-
story:
|
|
942
|
-
"Examples of different positioning options including alignment and offset configurations with proper content grouping.",
|
|
943
|
-
},
|
|
944
|
-
},
|
|
945
|
-
},
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
// 8. Grouping Showcase
|
|
949
|
-
export const GroupingShowcase: Story = {
|
|
950
|
-
render: () => (
|
|
951
|
-
<div className="space-y-8">
|
|
952
|
-
<div className="text-center">
|
|
953
|
-
<h3 className="text-fm-primary mb-2 font-medium">
|
|
954
|
-
DropdownMenuGroup Showcase
|
|
955
|
-
</h3>
|
|
956
|
-
<p className="text-fm-secondary text-sm">
|
|
957
|
-
Demonstrating logical grouping for better organization and
|
|
958
|
-
accessibility
|
|
959
|
-
</p>
|
|
960
|
-
</div>
|
|
961
|
-
|
|
962
|
-
<div className="flex justify-center">
|
|
963
|
-
<DropdownMenu>
|
|
964
|
-
<DropdownMenuTrigger asChild>
|
|
965
|
-
<Button variant="outline" className="gap-2">
|
|
966
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
967
|
-
Grouped Menu
|
|
968
|
-
<AngleDownIcon className="h-4 w-4" />
|
|
969
|
-
</Button>
|
|
970
|
-
</DropdownMenuTrigger>
|
|
971
|
-
<DropdownMenuContent className="w-56">
|
|
972
|
-
{/* File Operations Group */}
|
|
973
|
-
<DropdownMenuLabel>File Operations</DropdownMenuLabel>
|
|
974
|
-
<DropdownMenuSeparator />
|
|
975
|
-
<DropdownMenuGroup>
|
|
976
|
-
<DropdownMenuItem>
|
|
977
|
-
<FileChartIcon className="h-4 w-4" />
|
|
978
|
-
New File
|
|
979
|
-
<DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
|
|
980
|
-
</DropdownMenuItem>
|
|
981
|
-
<DropdownMenuItem>
|
|
982
|
-
<UploadIcon className="h-4 w-4" />
|
|
983
|
-
Upload
|
|
984
|
-
<DropdownMenuShortcut>⌘U</DropdownMenuShortcut>
|
|
985
|
-
</DropdownMenuItem>
|
|
986
|
-
<DropdownMenuItem>
|
|
987
|
-
<ImageIcon className="h-4 w-4" />
|
|
988
|
-
Import
|
|
989
|
-
<DropdownMenuShortcut>⌘I</DropdownMenuShortcut>
|
|
990
|
-
</DropdownMenuItem>
|
|
991
|
-
</DropdownMenuGroup>
|
|
992
|
-
|
|
993
|
-
<DropdownMenuSeparator />
|
|
994
|
-
|
|
995
|
-
{/* View Options Group */}
|
|
996
|
-
<DropdownMenuLabel>View Options</DropdownMenuLabel>
|
|
997
|
-
<DropdownMenuSeparator />
|
|
998
|
-
<DropdownMenuGroup>
|
|
999
|
-
<DropdownMenuItem>
|
|
1000
|
-
<EyeOpenIcon className="h-4 w-4" />
|
|
1001
|
-
Show Hidden Files
|
|
1002
|
-
</DropdownMenuItem>
|
|
1003
|
-
<DropdownMenuItem>
|
|
1004
|
-
<EyeCloseIcon className="h-4 w-4" />
|
|
1005
|
-
Hide Preview
|
|
1006
|
-
</DropdownMenuItem>
|
|
1007
|
-
<DropdownMenuItem>
|
|
1008
|
-
<SearchIcon className="h-4 w-4" />
|
|
1009
|
-
Search
|
|
1010
|
-
<DropdownMenuShortcut>⌘F</DropdownMenuShortcut>
|
|
1011
|
-
</DropdownMenuItem>
|
|
1012
|
-
</DropdownMenuGroup>
|
|
1013
|
-
|
|
1014
|
-
<DropdownMenuSeparator />
|
|
1015
|
-
|
|
1016
|
-
{/* Settings Group */}
|
|
1017
|
-
<DropdownMenuLabel>Settings</DropdownMenuLabel>
|
|
1018
|
-
<DropdownMenuSeparator />
|
|
1019
|
-
<DropdownMenuGroup>
|
|
1020
|
-
<DropdownMenuItem>
|
|
1021
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
1022
|
-
Preferences
|
|
1023
|
-
<DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
|
|
1024
|
-
</DropdownMenuItem>
|
|
1025
|
-
<DropdownMenuItem>
|
|
1026
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
1027
|
-
Account
|
|
1028
|
-
</DropdownMenuItem>
|
|
1029
|
-
</DropdownMenuGroup>
|
|
1030
|
-
|
|
1031
|
-
<DropdownMenuSeparator />
|
|
1032
|
-
|
|
1033
|
-
{/* Danger Zone Group */}
|
|
1034
|
-
<DropdownMenuGroup>
|
|
1035
|
-
<DropdownMenuItem variant="destructive">
|
|
1036
|
-
<CrossIcon className="h-4 w-4" />
|
|
1037
|
-
Reset All Settings
|
|
1038
|
-
</DropdownMenuItem>
|
|
1039
|
-
</DropdownMenuGroup>
|
|
1040
|
-
</DropdownMenuContent>
|
|
1041
|
-
</DropdownMenu>
|
|
1042
|
-
</div>
|
|
1043
|
-
</div>
|
|
1044
|
-
),
|
|
1045
|
-
parameters: {
|
|
1046
|
-
docs: {
|
|
1047
|
-
description: {
|
|
1048
|
-
story:
|
|
1049
|
-
"Showcase of DropdownMenuGroup component demonstrating how to logically group related menu items for better organization, navigation, and accessibility. Each group represents a semantic category of actions.",
|
|
1050
|
-
},
|
|
1051
|
-
},
|
|
825
|
+
)
|
|
1052
826
|
},
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
// 9. Arrow Showcase
|
|
1056
|
-
export const ArrowShowcase: Story = {
|
|
1057
|
-
render: () => (
|
|
1058
|
-
<div className="space-y-8">
|
|
1059
|
-
<div className="text-center">
|
|
1060
|
-
<h3 className="text-fm-primary mb-2 font-medium">
|
|
1061
|
-
DropdownArrow Showcase
|
|
1062
|
-
</h3>
|
|
1063
|
-
<p className="text-fm-secondary text-sm">
|
|
1064
|
-
Dropdown menus with arrow pointers for better visual connection to
|
|
1065
|
-
triggers
|
|
1066
|
-
</p>
|
|
1067
|
-
</div>
|
|
1068
|
-
|
|
1069
|
-
<div className="flex flex-wrap justify-center gap-8">
|
|
1070
|
-
{/* Basic Arrow */}
|
|
1071
|
-
<div className="space-y-4">
|
|
1072
|
-
<h4 className="text-fm-secondary text-center text-sm font-medium">
|
|
1073
|
-
Basic Arrow
|
|
1074
|
-
</h4>
|
|
1075
|
-
<DropdownMenu>
|
|
1076
|
-
<DropdownMenuTrigger asChild>
|
|
1077
|
-
<Button variant="outline" className="gap-2">
|
|
1078
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
1079
|
-
With Arrow
|
|
1080
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
1081
|
-
</Button>
|
|
1082
|
-
</DropdownMenuTrigger>
|
|
1083
|
-
<DropdownMenuContent>
|
|
1084
|
-
<DropdownArrow className="h-4 w-6" />
|
|
1085
|
-
<DropdownMenuGroup>
|
|
1086
|
-
<DropdownMenuItem>
|
|
1087
|
-
<EditBigIcon className="h-4 w-4" />
|
|
1088
|
-
Edit Item
|
|
1089
|
-
</DropdownMenuItem>
|
|
1090
|
-
<DropdownMenuItem>
|
|
1091
|
-
<TickIcon className="h-4 w-4" />
|
|
1092
|
-
Copy Item
|
|
1093
|
-
</DropdownMenuItem>
|
|
1094
|
-
<DropdownMenuItem>
|
|
1095
|
-
<ArrowRightIcon className="h-4 w-4" />
|
|
1096
|
-
Share Item
|
|
1097
|
-
</DropdownMenuItem>
|
|
1098
|
-
</DropdownMenuGroup>
|
|
1099
|
-
</DropdownMenuContent>
|
|
1100
|
-
</DropdownMenu>
|
|
1101
|
-
</div>
|
|
1102
|
-
|
|
1103
|
-
{/* Custom Styled Arrow */}
|
|
1104
|
-
<div className="space-y-4">
|
|
1105
|
-
<h4 className="text-fm-secondary text-center text-sm font-medium">
|
|
1106
|
-
Custom Styled Arrow
|
|
1107
|
-
</h4>
|
|
1108
|
-
<DropdownMenu>
|
|
1109
|
-
<DropdownMenuTrigger asChild>
|
|
1110
|
-
<Button>
|
|
1111
|
-
<AlertIcon className="h-4 w-4" />
|
|
1112
|
-
Blue Theme
|
|
1113
|
-
<AngleDownIcon className="h-4 w-4" />
|
|
1114
|
-
</Button>
|
|
1115
|
-
</DropdownMenuTrigger>
|
|
1116
|
-
<DropdownMenuContent
|
|
1117
|
-
classes={{
|
|
1118
|
-
root: "bg-blue-900/40 border-blue-500/20",
|
|
1119
|
-
border: "bg-gradient-to-r from-blue-500 to-cyan-500",
|
|
1120
|
-
}}
|
|
1121
|
-
>
|
|
1122
|
-
<DropdownArrow className="h-4 w-6 fill-blue-900" />
|
|
1123
|
-
<DropdownMenuGroup>
|
|
1124
|
-
<DropdownMenuItem
|
|
1125
|
-
classes={{
|
|
1126
|
-
root: "text-blue-200 hover:bg-blue-500/20 focus:bg-blue-500/20",
|
|
1127
|
-
}}
|
|
1128
|
-
>
|
|
1129
|
-
<TickIcon className="h-4 w-4" />
|
|
1130
|
-
Blue Action
|
|
1131
|
-
</DropdownMenuItem>
|
|
1132
|
-
<DropdownMenuItem
|
|
1133
|
-
classes={{
|
|
1134
|
-
root: "text-blue-200 hover:bg-blue-500/20 focus:bg-blue-500/20",
|
|
1135
|
-
}}
|
|
1136
|
-
>
|
|
1137
|
-
<AudioBarIcon className="h-4 w-4" />
|
|
1138
|
-
Another Action
|
|
1139
|
-
</DropdownMenuItem>
|
|
1140
|
-
</DropdownMenuGroup>
|
|
1141
|
-
</DropdownMenuContent>
|
|
1142
|
-
</DropdownMenu>
|
|
1143
|
-
</div>
|
|
1144
|
-
|
|
1145
|
-
{/* Arrow with Sub-menu */}
|
|
1146
|
-
<div className="space-y-4">
|
|
1147
|
-
<h4 className="text-fm-secondary text-center text-sm font-medium">
|
|
1148
|
-
Arrow with Sub-menu
|
|
1149
|
-
</h4>
|
|
1150
|
-
<DropdownMenu>
|
|
1151
|
-
<DropdownMenuTrigger asChild>
|
|
1152
|
-
<Button variant="text" className="gap-2">
|
|
1153
|
-
<PlusIcon className="h-4 w-4" />
|
|
1154
|
-
Create Menu
|
|
1155
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
1156
|
-
</Button>
|
|
1157
|
-
</DropdownMenuTrigger>
|
|
1158
|
-
<DropdownMenuContent>
|
|
1159
|
-
<DropdownArrow className="fill-fm-surface-frosted h-4 w-6" />
|
|
1160
|
-
<DropdownMenuLabel>Create New</DropdownMenuLabel>
|
|
1161
|
-
<DropdownMenuSeparator />
|
|
1162
|
-
<DropdownMenuGroup>
|
|
1163
|
-
<DropdownMenuItem>
|
|
1164
|
-
<FileChartIcon className="h-4 w-4" />
|
|
1165
|
-
New Document
|
|
1166
|
-
</DropdownMenuItem>
|
|
1167
|
-
<DropdownMenuSub>
|
|
1168
|
-
<DropdownMenuSubTrigger>
|
|
1169
|
-
<ImageIcon className="h-4 w-4" />
|
|
1170
|
-
Import From
|
|
1171
|
-
</DropdownMenuSubTrigger>
|
|
1172
|
-
<DropdownMenuSubContent>
|
|
1173
|
-
<DropdownArrow className="fill-fm-surface-frosted h-4 w-4" />
|
|
1174
|
-
<DropdownMenuGroup>
|
|
1175
|
-
<DropdownMenuItem>
|
|
1176
|
-
<UploadIcon className="h-4 w-4" />
|
|
1177
|
-
Local File
|
|
1178
|
-
</DropdownMenuItem>
|
|
1179
|
-
<DropdownMenuItem>
|
|
1180
|
-
<ArrowRightIcon className="h-4 w-4" />
|
|
1181
|
-
URL
|
|
1182
|
-
</DropdownMenuItem>
|
|
1183
|
-
<DropdownMenuItem>
|
|
1184
|
-
<SiteLogoIcon className="h-4 w-4" />
|
|
1185
|
-
Cloud Service
|
|
1186
|
-
</DropdownMenuItem>
|
|
1187
|
-
</DropdownMenuGroup>
|
|
1188
|
-
</DropdownMenuSubContent>
|
|
1189
|
-
</DropdownMenuSub>
|
|
1190
|
-
</DropdownMenuGroup>
|
|
1191
|
-
</DropdownMenuContent>
|
|
1192
|
-
</DropdownMenu>
|
|
1193
|
-
</div>
|
|
1194
|
-
</div>
|
|
1195
|
-
|
|
1196
|
-
<div className="text-center">
|
|
1197
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary inline-block max-w-lg rounded-lg border p-4">
|
|
1198
|
-
<h4 className="text-fm-primary mb-2 text-sm font-medium">
|
|
1199
|
-
Arrow Usage
|
|
1200
|
-
</h4>
|
|
1201
|
-
<p className="text-fm-secondary text-xs leading-relaxed">
|
|
1202
|
-
The DropdownArrow component creates a visual pointer from the menu
|
|
1203
|
-
to its trigger. It automatically inherits the menu's background
|
|
1204
|
-
color and can be customized with the className prop. Use it to
|
|
1205
|
-
improve the visual connection between triggers and their associated
|
|
1206
|
-
menus.
|
|
1207
|
-
</p>
|
|
1208
|
-
</div>
|
|
1209
|
-
</div>
|
|
1210
|
-
</div>
|
|
1211
|
-
),
|
|
1212
827
|
parameters: {
|
|
1213
828
|
docs: {
|
|
1214
829
|
description: {
|
|
1215
830
|
story:
|
|
1216
|
-
"
|
|
831
|
+
"Three product-realistic use cases in one export: (1) a track action menu attached to a track row — add to queue, like/unlike (stateful), add to playlist via sub-menu, share, download, remove; (2) a user account menu in a top-nav context with profile, subscription, settings, and log-out; (3) a settings context menu with nested sub-menus for audio and library configuration plus a destructive reset option.",
|
|
1217
832
|
},
|
|
1218
833
|
},
|
|
1219
834
|
},
|