@rovula/ui 0.1.20 → 0.1.22
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/cjs/bundle.css +316 -43
- package/dist/cjs/bundle.js +675 -675
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Badge/Badge.d.ts +40 -0
- package/dist/cjs/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/cjs/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/cjs/types/components/Badge/index.d.ts +2 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/cjs/types/components/Form/Form.d.ts +2 -1
- package/dist/cjs/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/cjs/types/index.d.ts +4 -1
- package/dist/cjs/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/cjs/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/cjs/types/utils/mergeRefs.d.ts +20 -0
- package/dist/components/Avatar/Avatar.styles.js +2 -2
- package/dist/components/Badge/Badge.js +36 -0
- package/dist/components/Badge/Badge.stories.js +51 -0
- package/dist/components/Badge/Badge.styles.js +62 -0
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/Dropdown/Dropdown.js +54 -163
- package/dist/components/Dropdown/Dropdown.stories.js +29 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +24 -13
- package/dist/components/DropdownMenu/DropdownMenu.stories.js +120 -88
- package/dist/components/Form/Form.js +11 -4
- package/dist/components/Form/Form.stories.js +27 -0
- package/dist/components/ScrollArea/ScrollArea.js +50 -0
- package/dist/components/ScrollArea/ScrollArea.stories.js +56 -0
- package/dist/components/TextInput/TextInput.js +6 -3
- package/dist/esm/bundle.css +316 -43
- package/dist/esm/bundle.js +1545 -1545
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Badge/Badge.d.ts +40 -0
- package/dist/esm/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/esm/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/esm/types/components/Badge/index.d.ts +2 -0
- package/dist/esm/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/esm/types/components/Form/Form.d.ts +2 -1
- package/dist/esm/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/esm/types/index.d.ts +4 -1
- package/dist/esm/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/esm/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/esm/types/utils/mergeRefs.d.ts +20 -0
- package/dist/index.d.ts +156 -74
- package/dist/index.js +3 -1
- package/dist/patterns/menu/Menu.js +95 -0
- package/dist/patterns/menu/Menu.stories.js +611 -0
- package/dist/src/theme/global.css +485 -57
- package/dist/utils/mergeRefs.js +42 -0
- package/package.json +1 -1
- package/src/components/Avatar/Avatar.styles.ts +2 -2
- package/src/components/Badge/Badge.stories.tsx +128 -0
- package/src/components/Badge/Badge.styles.ts +70 -0
- package/src/components/Badge/Badge.tsx +103 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +170 -1
- package/src/components/Dropdown/Dropdown.tsx +186 -276
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +1375 -253
- package/src/components/DropdownMenu/DropdownMenu.tsx +118 -55
- package/src/components/Form/Form.stories.tsx +70 -0
- package/src/components/Form/Form.tsx +23 -0
- package/src/components/ScrollArea/ScrollArea.stories.tsx +229 -0
- package/src/components/ScrollArea/ScrollArea.tsx +72 -0
- package/src/components/TextInput/TextInput.tsx +6 -3
- package/src/index.ts +4 -1
- package/src/patterns/menu/Menu.stories.tsx +1100 -0
- package/src/patterns/menu/Menu.tsx +282 -0
- package/src/theme/global.css +84 -11
- package/src/theme/themes/xspector/baseline.css +1 -1
- package/src/theme/themes/xspector/components/scrollbar.css +12 -0
- package/src/theme/tokens/baseline.css +3 -1
- package/src/theme/tokens/components/badge.css +54 -0
- package/src/theme/tokens/components/dropdown-menu.css +16 -5
- package/src/theme/tokens/components/scrollbar.css +18 -0
- package/src/utils/mergeRefs.ts +46 -0
- package/dist/cjs/types/components/Menu/Menu.d.ts +0 -65
- package/dist/cjs/types/components/Menu/helpers.d.ts +0 -19
- package/dist/cjs/types/components/Menu/index.d.ts +0 -4
- package/dist/components/Menu/Menu.js +0 -64
- package/dist/components/Menu/Menu.stories.js +0 -406
- package/dist/components/Menu/helpers.js +0 -28
- package/dist/components/Menu/index.js +0 -3
- package/dist/esm/types/components/Menu/Menu.d.ts +0 -65
- package/dist/esm/types/components/Menu/helpers.d.ts +0 -19
- package/dist/esm/types/components/Menu/index.d.ts +0 -4
- package/src/components/Menu/Menu.stories.tsx +0 -586
- package/src/components/Menu/Menu.tsx +0 -235
- package/src/components/Menu/helpers.ts +0 -45
- package/src/components/Menu/index.ts +0 -7
- package/src/theme/themes/xspector/components/dropdown-menu.css +0 -28
|
@@ -8,27 +8,29 @@ import {
|
|
|
8
8
|
DropdownMenuItem,
|
|
9
9
|
DropdownMenuLabel,
|
|
10
10
|
DropdownMenuPortal,
|
|
11
|
+
DropdownMenuRadioGroup,
|
|
12
|
+
DropdownMenuRadioItem,
|
|
11
13
|
DropdownMenuSeparator,
|
|
14
|
+
DropdownMenuShortcut,
|
|
12
15
|
DropdownMenuSub,
|
|
13
16
|
DropdownMenuSubContent,
|
|
14
17
|
DropdownMenuSubTrigger,
|
|
15
18
|
DropdownMenuTrigger,
|
|
16
19
|
} from "./DropdownMenu";
|
|
17
20
|
import Button from "../Button/Button";
|
|
18
|
-
import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu";
|
|
19
|
-
import Icon from "../Icon/Icon";
|
|
20
21
|
import ActionButton from "../ActionButton/ActionButton";
|
|
22
|
+
import Icon from "../Icon/Icon";
|
|
23
|
+
import { Input } from "../Input/Input";
|
|
21
24
|
|
|
22
25
|
const meta = {
|
|
23
26
|
title: "Components/DropdownMenu",
|
|
24
27
|
component: DropdownMenu,
|
|
25
|
-
// tags: ["autodocs"],
|
|
26
28
|
parameters: {
|
|
27
29
|
layout: "fullscreen",
|
|
28
30
|
},
|
|
29
31
|
decorators: [
|
|
30
32
|
(Story) => (
|
|
31
|
-
<div className="p-
|
|
33
|
+
<div className="p-10 flex gap-8 flex-wrap bg-workspace-surface min-h-screen">
|
|
32
34
|
<Story />
|
|
33
35
|
</div>
|
|
34
36
|
),
|
|
@@ -37,193 +39,453 @@ const meta = {
|
|
|
37
39
|
|
|
38
40
|
export default meta;
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
render: (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Figma: Normal dropdown / action menu
|
|
44
|
+
// Shows all item states: Default, Hover, Selected, Disabled, Selected+Disabled
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
export const AllStates = {
|
|
47
|
+
name: "All States (Normal)",
|
|
48
|
+
render: () => (
|
|
49
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
50
|
+
{/* Static — all states visible */}
|
|
51
|
+
<div>
|
|
52
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
53
|
+
All States
|
|
54
|
+
</p>
|
|
55
|
+
<DropdownMenu>
|
|
56
|
+
<DropdownMenuTrigger asChild>
|
|
57
|
+
<ActionButton variant="icon">
|
|
58
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
59
|
+
</ActionButton>
|
|
60
|
+
</DropdownMenuTrigger>
|
|
61
|
+
<DropdownMenuContent
|
|
62
|
+
className="relative"
|
|
63
|
+
style={{ position: "static", transform: "none" }}
|
|
64
|
+
>
|
|
65
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
66
|
+
<DropdownMenuItem className="!bg-[var(--dropdown-menu-hover-bg)]">
|
|
67
|
+
Option Description (Hover)
|
|
68
|
+
</DropdownMenuItem>
|
|
69
|
+
<DropdownMenuItem selected>Option Description</DropdownMenuItem>
|
|
70
|
+
<DropdownMenuItem disabled>Option Description</DropdownMenuItem>
|
|
71
|
+
<DropdownMenuItem selected disabled>
|
|
72
|
+
Option Description
|
|
73
|
+
</DropdownMenuItem>
|
|
74
|
+
</DropdownMenuContent>
|
|
75
|
+
</DropdownMenu>
|
|
68
76
|
</div>
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
|
|
78
|
+
{/* Interactive version */}
|
|
79
|
+
<div>
|
|
80
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
81
|
+
Interactive
|
|
82
|
+
</p>
|
|
83
|
+
<DropdownMenu>
|
|
84
|
+
<DropdownMenuTrigger asChild>
|
|
85
|
+
<Button variant="outline">Open Menu</Button>
|
|
86
|
+
</DropdownMenuTrigger>
|
|
87
|
+
<DropdownMenuContent>
|
|
88
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
89
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
90
|
+
<DropdownMenuItem selected>Option Description</DropdownMenuItem>
|
|
91
|
+
<DropdownMenuItem disabled>Option Description</DropdownMenuItem>
|
|
92
|
+
<DropdownMenuItem selected disabled>
|
|
93
|
+
Option Description
|
|
94
|
+
</DropdownMenuItem>
|
|
95
|
+
</DropdownMenuContent>
|
|
96
|
+
</DropdownMenu>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
),
|
|
71
100
|
} satisfies StoryObj;
|
|
72
101
|
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Figma: Have icon
|
|
104
|
+
// Items with leading icon
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
73
106
|
export const WithIcon = {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<
|
|
92
|
-
|
|
107
|
+
name: "With Icon",
|
|
108
|
+
render: () => (
|
|
109
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
110
|
+
<div>
|
|
111
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
112
|
+
All States — With Icon
|
|
113
|
+
</p>
|
|
114
|
+
<DropdownMenu>
|
|
115
|
+
<DropdownMenuTrigger asChild>
|
|
116
|
+
<ActionButton variant="icon">
|
|
117
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
118
|
+
</ActionButton>
|
|
119
|
+
</DropdownMenuTrigger>
|
|
120
|
+
<DropdownMenuContent
|
|
121
|
+
className="relative"
|
|
122
|
+
style={{ position: "static", transform: "none" }}
|
|
123
|
+
>
|
|
124
|
+
<DropdownMenuItem
|
|
125
|
+
icon={
|
|
93
126
|
<Icon
|
|
94
127
|
type="heroicons"
|
|
95
128
|
name="rocket-launch"
|
|
96
|
-
className="size-4"
|
|
129
|
+
className="size-4 shrink-0"
|
|
97
130
|
/>
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
131
|
+
}
|
|
132
|
+
>
|
|
133
|
+
Option Description
|
|
134
|
+
</DropdownMenuItem>
|
|
135
|
+
<DropdownMenuItem
|
|
136
|
+
className="!bg-[var(--dropdown-menu-hover-bg)]"
|
|
137
|
+
icon={
|
|
101
138
|
<Icon
|
|
102
139
|
type="heroicons"
|
|
103
140
|
name="rocket-launch"
|
|
104
|
-
className="size-4"
|
|
141
|
+
className="size-4 shrink-0"
|
|
105
142
|
/>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
143
|
+
}
|
|
144
|
+
>
|
|
145
|
+
Option Description (Hover)
|
|
146
|
+
</DropdownMenuItem>
|
|
147
|
+
<DropdownMenuItem
|
|
148
|
+
selected
|
|
149
|
+
icon={
|
|
109
150
|
<Icon
|
|
110
151
|
type="heroicons"
|
|
111
152
|
name="rocket-launch"
|
|
112
|
-
className="size-4"
|
|
153
|
+
className="size-4 shrink-0"
|
|
113
154
|
/>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
155
|
+
}
|
|
156
|
+
>
|
|
157
|
+
Option Description (Selected)
|
|
158
|
+
</DropdownMenuItem>
|
|
159
|
+
<DropdownMenuItem
|
|
160
|
+
disabled
|
|
161
|
+
icon={
|
|
162
|
+
<Icon
|
|
163
|
+
type="heroicons"
|
|
164
|
+
name="rocket-launch"
|
|
165
|
+
className="size-4 shrink-0"
|
|
166
|
+
/>
|
|
167
|
+
}
|
|
168
|
+
>
|
|
169
|
+
Option Description (Disabled)
|
|
170
|
+
</DropdownMenuItem>
|
|
171
|
+
<DropdownMenuItem
|
|
172
|
+
selected
|
|
173
|
+
disabled
|
|
174
|
+
icon={
|
|
175
|
+
<Icon
|
|
176
|
+
type="heroicons"
|
|
177
|
+
name="rocket-launch"
|
|
178
|
+
className="size-4 shrink-0"
|
|
179
|
+
/>
|
|
180
|
+
}
|
|
181
|
+
>
|
|
182
|
+
Option Description (Selected + Disabled)
|
|
183
|
+
</DropdownMenuItem>
|
|
184
|
+
</DropdownMenuContent>
|
|
185
|
+
</DropdownMenu>
|
|
119
186
|
</div>
|
|
120
|
-
|
|
121
|
-
|
|
187
|
+
|
|
188
|
+
<div>
|
|
189
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
190
|
+
Interactive
|
|
191
|
+
</p>
|
|
192
|
+
<DropdownMenu>
|
|
193
|
+
<DropdownMenuTrigger asChild>
|
|
194
|
+
<Button variant="outline">Open Menu</Button>
|
|
195
|
+
</DropdownMenuTrigger>
|
|
196
|
+
<DropdownMenuContent>
|
|
197
|
+
<DropdownMenuItem
|
|
198
|
+
icon={
|
|
199
|
+
<Icon
|
|
200
|
+
type="heroicons"
|
|
201
|
+
name="rocket-launch"
|
|
202
|
+
className="size-4 shrink-0"
|
|
203
|
+
/>
|
|
204
|
+
}
|
|
205
|
+
>
|
|
206
|
+
Launch
|
|
207
|
+
</DropdownMenuItem>
|
|
208
|
+
<DropdownMenuItem
|
|
209
|
+
icon={
|
|
210
|
+
<Icon
|
|
211
|
+
type="heroicons"
|
|
212
|
+
name="pencil"
|
|
213
|
+
className="size-4 shrink-0"
|
|
214
|
+
/>
|
|
215
|
+
}
|
|
216
|
+
>
|
|
217
|
+
Edit
|
|
218
|
+
</DropdownMenuItem>
|
|
219
|
+
<DropdownMenuItem
|
|
220
|
+
icon={
|
|
221
|
+
<Icon
|
|
222
|
+
type="heroicons"
|
|
223
|
+
name="document-duplicate"
|
|
224
|
+
className="size-4 shrink-0"
|
|
225
|
+
/>
|
|
226
|
+
}
|
|
227
|
+
>
|
|
228
|
+
Duplicate
|
|
229
|
+
</DropdownMenuItem>
|
|
230
|
+
<DropdownMenuItem
|
|
231
|
+
disabled
|
|
232
|
+
icon={
|
|
233
|
+
<Icon
|
|
234
|
+
type="heroicons"
|
|
235
|
+
name="trash"
|
|
236
|
+
className="size-4 shrink-0"
|
|
237
|
+
/>
|
|
238
|
+
}
|
|
239
|
+
>
|
|
240
|
+
Delete
|
|
241
|
+
</DropdownMenuItem>
|
|
242
|
+
</DropdownMenuContent>
|
|
243
|
+
</DropdownMenu>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
),
|
|
122
247
|
} satisfies StoryObj;
|
|
123
248
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
};
|
|
249
|
+
// ---------------------------------------------------------------------------
|
|
250
|
+
// Figma: Checkbox items (Have icon=No, Checkbox=Yes)
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
export const WithCheckbox = {
|
|
253
|
+
name: "With Checkbox",
|
|
254
|
+
render: () => {
|
|
255
|
+
const [checked1, setChecked1] = useState(false);
|
|
256
|
+
const [checked2, setChecked2] = useState(true);
|
|
257
|
+
const [checked3, setChecked3] = useState(false);
|
|
258
|
+
|
|
135
259
|
return (
|
|
136
|
-
<div className="flex
|
|
137
|
-
<div
|
|
260
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
261
|
+
<div>
|
|
262
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
263
|
+
All States — Checkbox
|
|
264
|
+
</p>
|
|
138
265
|
<DropdownMenu>
|
|
139
266
|
<DropdownMenuTrigger asChild>
|
|
140
|
-
<
|
|
267
|
+
<ActionButton variant="icon">
|
|
268
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
269
|
+
</ActionButton>
|
|
141
270
|
</DropdownMenuTrigger>
|
|
142
|
-
<DropdownMenuContent
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
271
|
+
<DropdownMenuContent
|
|
272
|
+
className="relative"
|
|
273
|
+
style={{ position: "static", transform: "none" }}
|
|
274
|
+
>
|
|
275
|
+
<DropdownMenuCheckboxItem>
|
|
276
|
+
Option Description
|
|
277
|
+
</DropdownMenuCheckboxItem>
|
|
278
|
+
<DropdownMenuCheckboxItem className="!bg-[var(--dropdown-menu-hover-bg)]">
|
|
279
|
+
Option Description (Hover)
|
|
280
|
+
</DropdownMenuCheckboxItem>
|
|
281
|
+
<DropdownMenuCheckboxItem checked>
|
|
282
|
+
Option Description
|
|
283
|
+
</DropdownMenuCheckboxItem>
|
|
284
|
+
<DropdownMenuCheckboxItem disabled>
|
|
285
|
+
Option Description
|
|
286
|
+
</DropdownMenuCheckboxItem>
|
|
287
|
+
<DropdownMenuCheckboxItem checked disabled>
|
|
288
|
+
Option Description
|
|
289
|
+
</DropdownMenuCheckboxItem>
|
|
155
290
|
</DropdownMenuContent>
|
|
156
291
|
</DropdownMenu>
|
|
157
292
|
</div>
|
|
158
|
-
</div>
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
} satisfies StoryObj;
|
|
162
293
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// fullwidth: true,
|
|
168
|
-
},
|
|
169
|
-
render: (args) => {
|
|
170
|
-
type Checked = DropdownMenuCheckboxItemProps["checked"];
|
|
171
|
-
console.log("args ", args);
|
|
172
|
-
const props: typeof args = {
|
|
173
|
-
...args,
|
|
174
|
-
};
|
|
175
|
-
return (
|
|
176
|
-
<div className="flex flex-row gap-4 w-full">
|
|
177
|
-
<div className="flex flex-1 justify-center items-center space-x-2">
|
|
294
|
+
<div>
|
|
295
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
296
|
+
Interactive
|
|
297
|
+
</p>
|
|
178
298
|
<DropdownMenu>
|
|
179
299
|
<DropdownMenuTrigger asChild>
|
|
180
|
-
<Button variant="outline">Open</Button>
|
|
300
|
+
<Button variant="outline">Open Menu</Button>
|
|
181
301
|
</DropdownMenuTrigger>
|
|
182
302
|
<DropdownMenuContent>
|
|
183
|
-
<DropdownMenuCheckboxItem
|
|
303
|
+
<DropdownMenuCheckboxItem
|
|
304
|
+
checked={checked1}
|
|
305
|
+
onCheckedChange={setChecked1}
|
|
306
|
+
>
|
|
184
307
|
Option Description
|
|
185
308
|
</DropdownMenuCheckboxItem>
|
|
186
|
-
<DropdownMenuCheckboxItem
|
|
309
|
+
<DropdownMenuCheckboxItem
|
|
310
|
+
checked={checked2}
|
|
311
|
+
onCheckedChange={setChecked2}
|
|
312
|
+
>
|
|
187
313
|
Option Description
|
|
188
314
|
</DropdownMenuCheckboxItem>
|
|
189
|
-
<DropdownMenuCheckboxItem
|
|
315
|
+
<DropdownMenuCheckboxItem
|
|
316
|
+
checked={checked3}
|
|
317
|
+
onCheckedChange={setChecked3}
|
|
318
|
+
>
|
|
190
319
|
Option Description
|
|
191
320
|
</DropdownMenuCheckboxItem>
|
|
192
|
-
<DropdownMenuCheckboxItem
|
|
321
|
+
<DropdownMenuCheckboxItem disabled>
|
|
193
322
|
Option Description
|
|
194
323
|
</DropdownMenuCheckboxItem>
|
|
195
|
-
|
|
324
|
+
</DropdownMenuContent>
|
|
325
|
+
</DropdownMenu>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
},
|
|
330
|
+
} satisfies StoryObj;
|
|
331
|
+
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
// Figma: Have section (DropdownMenuLabel as section header)
|
|
334
|
+
// ---------------------------------------------------------------------------
|
|
335
|
+
export const WithSection = {
|
|
336
|
+
name: "Have Section",
|
|
337
|
+
render: () => (
|
|
338
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
339
|
+
<div>
|
|
340
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
341
|
+
With Section Header
|
|
342
|
+
</p>
|
|
343
|
+
<DropdownMenu>
|
|
344
|
+
<DropdownMenuTrigger asChild>
|
|
345
|
+
<ActionButton variant="icon">
|
|
346
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
347
|
+
</ActionButton>
|
|
348
|
+
</DropdownMenuTrigger>
|
|
349
|
+
<DropdownMenuContent
|
|
350
|
+
className="relative"
|
|
351
|
+
style={{ position: "static", transform: "none" }}
|
|
352
|
+
>
|
|
353
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
354
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
355
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
356
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
357
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
358
|
+
<DropdownMenuSeparator />
|
|
359
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
360
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
361
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
362
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
363
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
364
|
+
</DropdownMenuContent>
|
|
365
|
+
</DropdownMenu>
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
<div>
|
|
369
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
370
|
+
Interactive
|
|
371
|
+
</p>
|
|
372
|
+
<DropdownMenu>
|
|
373
|
+
<DropdownMenuTrigger asChild>
|
|
374
|
+
<Button variant="outline">Open Menu</Button>
|
|
375
|
+
</DropdownMenuTrigger>
|
|
376
|
+
<DropdownMenuContent>
|
|
377
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
378
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
379
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
380
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
381
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
382
|
+
<DropdownMenuSeparator />
|
|
383
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
384
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
385
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
386
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
387
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
388
|
+
</DropdownMenuContent>
|
|
389
|
+
</DropdownMenu>
|
|
390
|
+
</div>
|
|
391
|
+
</div>
|
|
392
|
+
),
|
|
393
|
+
} satisfies StoryObj;
|
|
394
|
+
|
|
395
|
+
// ---------------------------------------------------------------------------
|
|
396
|
+
// Figma: Have search
|
|
397
|
+
// Dropdown with search input at the top
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
export const WithSearch = {
|
|
400
|
+
name: "Have Search",
|
|
401
|
+
render: () => {
|
|
402
|
+
const [query, setQuery] = useState("");
|
|
403
|
+
const allOptions = [
|
|
404
|
+
"Option Description",
|
|
405
|
+
"Project Alpha",
|
|
406
|
+
"Project Beta",
|
|
407
|
+
"Project Gamma",
|
|
408
|
+
"Project Delta",
|
|
409
|
+
"Project Epsilon",
|
|
410
|
+
"Project Zeta",
|
|
411
|
+
"Project Eta",
|
|
412
|
+
"Project Theta",
|
|
413
|
+
];
|
|
414
|
+
const filtered = allOptions.filter((o) =>
|
|
415
|
+
o.toLowerCase().includes(query.toLowerCase()),
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
420
|
+
<div>
|
|
421
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
422
|
+
With Search Field
|
|
423
|
+
</p>
|
|
424
|
+
<DropdownMenu>
|
|
425
|
+
<DropdownMenuTrigger asChild>
|
|
426
|
+
<ActionButton variant="icon">
|
|
427
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
428
|
+
</ActionButton>
|
|
429
|
+
</DropdownMenuTrigger>
|
|
430
|
+
<DropdownMenuContent
|
|
431
|
+
className="relative w-[230px]"
|
|
432
|
+
style={{ position: "static", transform: "none" }}
|
|
433
|
+
onInteractOutside={(e: Event) => e.preventDefault()}
|
|
434
|
+
>
|
|
435
|
+
<div className="flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]">
|
|
196
436
|
<Icon
|
|
197
437
|
type="heroicons"
|
|
198
|
-
name="
|
|
199
|
-
className="size-
|
|
438
|
+
name="magnifying-glass"
|
|
439
|
+
className="size-[14px] shrink-0 text-text-g-contrast-medium mr-1"
|
|
200
440
|
/>
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
441
|
+
<Input
|
|
442
|
+
variant="flat"
|
|
443
|
+
size="sm"
|
|
444
|
+
className="flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium"
|
|
445
|
+
placeholder="Search"
|
|
446
|
+
value={query}
|
|
447
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
208
448
|
/>
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
449
|
+
</div>
|
|
450
|
+
{filtered.map((label) => (
|
|
451
|
+
<DropdownMenuItem key={label}>{label}</DropdownMenuItem>
|
|
452
|
+
))}
|
|
453
|
+
{filtered.length === 0 && (
|
|
454
|
+
<div className="px-4 py-3 typography-subtitle4 text-text-g-contrast-medium">
|
|
455
|
+
No results found
|
|
456
|
+
</div>
|
|
457
|
+
)}
|
|
458
|
+
</DropdownMenuContent>
|
|
459
|
+
</DropdownMenu>
|
|
460
|
+
</div>
|
|
461
|
+
|
|
462
|
+
<div>
|
|
463
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
464
|
+
Interactive
|
|
465
|
+
</p>
|
|
466
|
+
<DropdownMenu>
|
|
467
|
+
<DropdownMenuTrigger asChild>
|
|
468
|
+
<Button variant="outline">Open Menu</Button>
|
|
469
|
+
</DropdownMenuTrigger>
|
|
470
|
+
<DropdownMenuContent className="w-[230px]">
|
|
471
|
+
<div className="flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]">
|
|
212
472
|
<Icon
|
|
213
473
|
type="heroicons"
|
|
214
|
-
name="
|
|
215
|
-
className="size-
|
|
474
|
+
name="magnifying-glass"
|
|
475
|
+
className="size-[14px] shrink-0 text-text-g-contrast-medium mr-1"
|
|
216
476
|
/>
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
name="rocket-launch"
|
|
223
|
-
className="size-4"
|
|
477
|
+
<Input
|
|
478
|
+
variant="flat"
|
|
479
|
+
size="sm"
|
|
480
|
+
className="flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium"
|
|
481
|
+
placeholder="Search"
|
|
224
482
|
/>
|
|
225
|
-
|
|
226
|
-
</
|
|
483
|
+
</div>
|
|
484
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
485
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
486
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
487
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
488
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
227
489
|
</DropdownMenuContent>
|
|
228
490
|
</DropdownMenu>
|
|
229
491
|
</div>
|
|
@@ -232,84 +494,282 @@ export const Checkboxes = {
|
|
|
232
494
|
},
|
|
233
495
|
} satisfies StoryObj;
|
|
234
496
|
|
|
497
|
+
// ---------------------------------------------------------------------------
|
|
498
|
+
// Figma: Can scroll — long list, overflow-y scrollable
|
|
499
|
+
// ---------------------------------------------------------------------------
|
|
500
|
+
export const CanScroll = {
|
|
501
|
+
name: "Can Scroll",
|
|
502
|
+
render: () => (
|
|
503
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
504
|
+
<div>
|
|
505
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
506
|
+
Scrollable List
|
|
507
|
+
</p>
|
|
508
|
+
<DropdownMenu>
|
|
509
|
+
<DropdownMenuTrigger asChild>
|
|
510
|
+
<ActionButton variant="icon">
|
|
511
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
512
|
+
</ActionButton>
|
|
513
|
+
</DropdownMenuTrigger>
|
|
514
|
+
<DropdownMenuContent
|
|
515
|
+
className="relative max-h-[270px] overflow-y-auto"
|
|
516
|
+
style={{ position: "static", transform: "none" }}
|
|
517
|
+
>
|
|
518
|
+
{Array.from({ length: 10 }, (_, i) => (
|
|
519
|
+
<DropdownMenuItem key={i}>
|
|
520
|
+
Option Description {i + 1}
|
|
521
|
+
</DropdownMenuItem>
|
|
522
|
+
))}
|
|
523
|
+
</DropdownMenuContent>
|
|
524
|
+
</DropdownMenu>
|
|
525
|
+
</div>
|
|
526
|
+
|
|
527
|
+
<div>
|
|
528
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
529
|
+
Interactive
|
|
530
|
+
</p>
|
|
531
|
+
<DropdownMenu>
|
|
532
|
+
<DropdownMenuTrigger asChild>
|
|
533
|
+
<Button variant="outline">Open Menu</Button>
|
|
534
|
+
</DropdownMenuTrigger>
|
|
535
|
+
<DropdownMenuContent className="max-h-[270px] overflow-y-auto">
|
|
536
|
+
{Array.from({ length: 10 }, (_, i) => (
|
|
537
|
+
<DropdownMenuItem key={i}>
|
|
538
|
+
Option Description {i + 1}
|
|
539
|
+
</DropdownMenuItem>
|
|
540
|
+
))}
|
|
541
|
+
</DropdownMenuContent>
|
|
542
|
+
</DropdownMenu>
|
|
543
|
+
</div>
|
|
544
|
+
</div>
|
|
545
|
+
),
|
|
546
|
+
} satisfies StoryObj;
|
|
547
|
+
|
|
548
|
+
// ---------------------------------------------------------------------------
|
|
549
|
+
// Figma: Double scroll — two separate scrollable sections with section headers
|
|
550
|
+
// ---------------------------------------------------------------------------
|
|
551
|
+
export const DoubleScroll = {
|
|
552
|
+
name: "Double Scroll",
|
|
553
|
+
render: () => (
|
|
554
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
555
|
+
<div>
|
|
556
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
557
|
+
Two Scrollable Sections
|
|
558
|
+
</p>
|
|
559
|
+
<DropdownMenu>
|
|
560
|
+
<DropdownMenuTrigger asChild>
|
|
561
|
+
<ActionButton variant="icon">
|
|
562
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
563
|
+
</ActionButton>
|
|
564
|
+
</DropdownMenuTrigger>
|
|
565
|
+
<DropdownMenuContent
|
|
566
|
+
className="relative"
|
|
567
|
+
style={{ position: "static", transform: "none" }}
|
|
568
|
+
>
|
|
569
|
+
<DropdownMenuLabel>Section A</DropdownMenuLabel>
|
|
570
|
+
<div className="max-h-[270px] overflow-y-auto">
|
|
571
|
+
{Array.from({ length: 5 }, (_, i) => (
|
|
572
|
+
<DropdownMenuItem key={i}>
|
|
573
|
+
Option Description {i + 1}
|
|
574
|
+
</DropdownMenuItem>
|
|
575
|
+
))}
|
|
576
|
+
</div>
|
|
577
|
+
<DropdownMenuSeparator />
|
|
578
|
+
<DropdownMenuLabel>Section B</DropdownMenuLabel>
|
|
579
|
+
<div className="max-h-[216px] overflow-y-auto">
|
|
580
|
+
{Array.from({ length: 4 }, (_, i) => (
|
|
581
|
+
<DropdownMenuItem key={i}>
|
|
582
|
+
Option Description {i + 1}
|
|
583
|
+
</DropdownMenuItem>
|
|
584
|
+
))}
|
|
585
|
+
</div>
|
|
586
|
+
</DropdownMenuContent>
|
|
587
|
+
</DropdownMenu>
|
|
588
|
+
</div>
|
|
589
|
+
|
|
590
|
+
<div>
|
|
591
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
592
|
+
Interactive
|
|
593
|
+
</p>
|
|
594
|
+
<DropdownMenu>
|
|
595
|
+
<DropdownMenuTrigger asChild>
|
|
596
|
+
<Button variant="outline">Open Menu</Button>
|
|
597
|
+
</DropdownMenuTrigger>
|
|
598
|
+
<DropdownMenuContent>
|
|
599
|
+
<DropdownMenuLabel>Section A</DropdownMenuLabel>
|
|
600
|
+
<div className="max-h-[270px] overflow-y-auto">
|
|
601
|
+
{Array.from({ length: 5 }, (_, i) => (
|
|
602
|
+
<DropdownMenuItem key={i}>
|
|
603
|
+
Option Description {i + 1}
|
|
604
|
+
</DropdownMenuItem>
|
|
605
|
+
))}
|
|
606
|
+
</div>
|
|
607
|
+
<DropdownMenuSeparator />
|
|
608
|
+
<DropdownMenuLabel>Section B</DropdownMenuLabel>
|
|
609
|
+
<div className="max-h-[216px] overflow-y-auto">
|
|
610
|
+
{Array.from({ length: 4 }, (_, i) => (
|
|
611
|
+
<DropdownMenuItem key={i}>
|
|
612
|
+
Option Description {i + 1}
|
|
613
|
+
</DropdownMenuItem>
|
|
614
|
+
))}
|
|
615
|
+
</div>
|
|
616
|
+
</DropdownMenuContent>
|
|
617
|
+
</DropdownMenu>
|
|
618
|
+
</div>
|
|
619
|
+
</div>
|
|
620
|
+
),
|
|
621
|
+
} satisfies StoryObj;
|
|
622
|
+
|
|
623
|
+
// ---------------------------------------------------------------------------
|
|
624
|
+
// Figma: Sub menu (existing, preserved)
|
|
625
|
+
// ---------------------------------------------------------------------------
|
|
235
626
|
export const SubMenu = {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
627
|
+
name: "Sub Menu",
|
|
628
|
+
render: () => (
|
|
629
|
+
<div className="flex gap-8 items-center flex-wrap">
|
|
630
|
+
<DropdownMenu>
|
|
631
|
+
<DropdownMenuTrigger asChild>
|
|
632
|
+
<Button variant="outline">Open Menu</Button>
|
|
633
|
+
</DropdownMenuTrigger>
|
|
634
|
+
<DropdownMenuContent>
|
|
635
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
636
|
+
<DropdownMenuSeparator />
|
|
637
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
638
|
+
<DropdownMenuItem>Billing</DropdownMenuItem>
|
|
639
|
+
<DropdownMenuItem>Team</DropdownMenuItem>
|
|
640
|
+
<DropdownMenuSeparator />
|
|
641
|
+
<DropdownMenuGroup>
|
|
642
|
+
<DropdownMenuSub>
|
|
643
|
+
<DropdownMenuSubTrigger>
|
|
644
|
+
<Icon
|
|
645
|
+
type="heroicons"
|
|
646
|
+
name="user-group"
|
|
647
|
+
className="size-4 shrink-0"
|
|
648
|
+
/>
|
|
649
|
+
Invite users
|
|
650
|
+
</DropdownMenuSubTrigger>
|
|
651
|
+
<DropdownMenuPortal>
|
|
652
|
+
<DropdownMenuSubContent>
|
|
653
|
+
<DropdownMenuItem>Email</DropdownMenuItem>
|
|
654
|
+
<DropdownMenuItem>Message</DropdownMenuItem>
|
|
655
|
+
<DropdownMenuSeparator />
|
|
656
|
+
<DropdownMenuItem>More...</DropdownMenuItem>
|
|
657
|
+
</DropdownMenuSubContent>
|
|
658
|
+
</DropdownMenuPortal>
|
|
659
|
+
</DropdownMenuSub>
|
|
660
|
+
<DropdownMenuCheckboxItem>Panel</DropdownMenuCheckboxItem>
|
|
661
|
+
</DropdownMenuGroup>
|
|
662
|
+
</DropdownMenuContent>
|
|
663
|
+
</DropdownMenu>
|
|
664
|
+
</div>
|
|
665
|
+
),
|
|
666
|
+
} satisfies StoryObj;
|
|
667
|
+
|
|
668
|
+
// ---------------------------------------------------------------------------
|
|
669
|
+
// Figma: Radio items — single select via DropdownMenuRadioGroup
|
|
670
|
+
// ---------------------------------------------------------------------------
|
|
671
|
+
export const WithRadio = {
|
|
672
|
+
name: "With Radio",
|
|
673
|
+
render: () => {
|
|
674
|
+
const [theme, setTheme] = useState("light");
|
|
675
|
+
const [position, setPosition] = useState("top");
|
|
676
|
+
|
|
246
677
|
return (
|
|
247
|
-
<div className="flex
|
|
248
|
-
<div
|
|
678
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
679
|
+
<div>
|
|
680
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
681
|
+
All States — Radio
|
|
682
|
+
</p>
|
|
249
683
|
<DropdownMenu>
|
|
250
|
-
<DropdownMenuTrigger>
|
|
684
|
+
<DropdownMenuTrigger asChild>
|
|
685
|
+
<ActionButton variant="icon">
|
|
686
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
687
|
+
</ActionButton>
|
|
688
|
+
</DropdownMenuTrigger>
|
|
689
|
+
<DropdownMenuContent
|
|
690
|
+
className="relative"
|
|
691
|
+
style={{ position: "static", transform: "none" }}
|
|
692
|
+
>
|
|
693
|
+
<DropdownMenuRadioGroup value="light">
|
|
694
|
+
<DropdownMenuRadioItem value="unselected">
|
|
695
|
+
Option Description
|
|
696
|
+
</DropdownMenuRadioItem>
|
|
697
|
+
<DropdownMenuRadioItem
|
|
698
|
+
value="unselected2"
|
|
699
|
+
className="!bg-[var(--dropdown-menu-hover-bg)]"
|
|
700
|
+
>
|
|
701
|
+
Option Description (Hover)
|
|
702
|
+
</DropdownMenuRadioItem>
|
|
703
|
+
<DropdownMenuRadioItem value="light">
|
|
704
|
+
Option Description (Selected)
|
|
705
|
+
</DropdownMenuRadioItem>
|
|
706
|
+
<DropdownMenuRadioItem value="dis" disabled>
|
|
707
|
+
Option Description (Disabled)
|
|
708
|
+
</DropdownMenuRadioItem>
|
|
709
|
+
<DropdownMenuRadioItem value="light" disabled>
|
|
710
|
+
Option Description (Selected + Disabled)
|
|
711
|
+
</DropdownMenuRadioItem>
|
|
712
|
+
</DropdownMenuRadioGroup>
|
|
713
|
+
</DropdownMenuContent>
|
|
714
|
+
</DropdownMenu>
|
|
715
|
+
</div>
|
|
716
|
+
|
|
717
|
+
<div>
|
|
718
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
719
|
+
Interactive — Theme
|
|
720
|
+
</p>
|
|
721
|
+
<DropdownMenu>
|
|
722
|
+
<DropdownMenuTrigger asChild>
|
|
723
|
+
<Button variant="outline">Theme: {theme}</Button>
|
|
724
|
+
</DropdownMenuTrigger>
|
|
251
725
|
<DropdownMenuContent>
|
|
252
|
-
<DropdownMenuLabel>
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
<span>Invite users</span>
|
|
263
|
-
</DropdownMenuSubTrigger>
|
|
264
|
-
<DropdownMenuPortal>
|
|
265
|
-
<DropdownMenuSubContent>
|
|
266
|
-
<DropdownMenuItem>
|
|
267
|
-
<span>Email</span>
|
|
268
|
-
</DropdownMenuItem>
|
|
269
|
-
<DropdownMenuItem>
|
|
270
|
-
<span>Message</span>
|
|
271
|
-
</DropdownMenuItem>
|
|
272
|
-
<DropdownMenuSeparator />
|
|
273
|
-
<DropdownMenuItem>
|
|
274
|
-
<span>More...</span>
|
|
275
|
-
</DropdownMenuItem>
|
|
276
|
-
</DropdownMenuSubContent>
|
|
277
|
-
</DropdownMenuPortal>
|
|
278
|
-
</DropdownMenuSub>
|
|
279
|
-
<DropdownMenuCheckboxItem>Panel</DropdownMenuCheckboxItem>
|
|
280
|
-
</DropdownMenuGroup>
|
|
726
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
727
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
728
|
+
<DropdownMenuRadioItem value="light">
|
|
729
|
+
Light
|
|
730
|
+
</DropdownMenuRadioItem>
|
|
731
|
+
<DropdownMenuRadioItem value="dark">Dark</DropdownMenuRadioItem>
|
|
732
|
+
<DropdownMenuRadioItem value="system">
|
|
733
|
+
System
|
|
734
|
+
</DropdownMenuRadioItem>
|
|
735
|
+
</DropdownMenuRadioGroup>
|
|
281
736
|
</DropdownMenuContent>
|
|
282
737
|
</DropdownMenu>
|
|
283
738
|
</div>
|
|
284
|
-
</div>
|
|
285
|
-
);
|
|
286
|
-
},
|
|
287
|
-
} satisfies StoryObj;
|
|
288
739
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// fullwidth: true,
|
|
294
|
-
},
|
|
295
|
-
render: (args) => {
|
|
296
|
-
console.log("args ", args);
|
|
297
|
-
const props: typeof args = {
|
|
298
|
-
...args,
|
|
299
|
-
};
|
|
300
|
-
return (
|
|
301
|
-
<div className="flex flex-row gap-4 w-full">
|
|
302
|
-
<div className="flex flex-1 justify-center items-center space-x-2">
|
|
740
|
+
<div>
|
|
741
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
742
|
+
Interactive — Multiple Groups
|
|
743
|
+
</p>
|
|
303
744
|
<DropdownMenu>
|
|
304
|
-
<DropdownMenuTrigger>
|
|
305
|
-
<
|
|
745
|
+
<DropdownMenuTrigger asChild>
|
|
746
|
+
<Button variant="outline">Open Menu</Button>
|
|
306
747
|
</DropdownMenuTrigger>
|
|
307
748
|
<DropdownMenuContent>
|
|
308
|
-
<
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
749
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
750
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
751
|
+
<DropdownMenuRadioItem value="light">
|
|
752
|
+
Light
|
|
753
|
+
</DropdownMenuRadioItem>
|
|
754
|
+
<DropdownMenuRadioItem value="dark">Dark</DropdownMenuRadioItem>
|
|
755
|
+
<DropdownMenuRadioItem value="system">
|
|
756
|
+
System
|
|
757
|
+
</DropdownMenuRadioItem>
|
|
758
|
+
</DropdownMenuRadioGroup>
|
|
759
|
+
<DropdownMenuSeparator />
|
|
760
|
+
<DropdownMenuLabel>Position</DropdownMenuLabel>
|
|
761
|
+
<DropdownMenuRadioGroup
|
|
762
|
+
value={position}
|
|
763
|
+
onValueChange={setPosition}
|
|
764
|
+
>
|
|
765
|
+
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
|
|
766
|
+
<DropdownMenuRadioItem value="bottom">
|
|
767
|
+
Bottom
|
|
768
|
+
</DropdownMenuRadioItem>
|
|
769
|
+
<DropdownMenuRadioItem value="right">
|
|
770
|
+
Right
|
|
771
|
+
</DropdownMenuRadioItem>
|
|
772
|
+
</DropdownMenuRadioGroup>
|
|
313
773
|
</DropdownMenuContent>
|
|
314
774
|
</DropdownMenu>
|
|
315
775
|
</div>
|
|
@@ -318,32 +778,160 @@ export const OnIcon = {
|
|
|
318
778
|
},
|
|
319
779
|
} satisfies StoryObj;
|
|
320
780
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const props: typeof args = {
|
|
330
|
-
...args,
|
|
331
|
-
};
|
|
781
|
+
// ---------------------------------------------------------------------------
|
|
782
|
+
// Radio with Icon — single select with leading icon via icon prop
|
|
783
|
+
// ---------------------------------------------------------------------------
|
|
784
|
+
export const WithRadioAndIcon = {
|
|
785
|
+
name: "With Radio + Icon",
|
|
786
|
+
render: () => {
|
|
787
|
+
const [theme, setTheme] = useState("dark");
|
|
788
|
+
|
|
332
789
|
return (
|
|
333
|
-
<div className="flex
|
|
334
|
-
<div
|
|
790
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
791
|
+
<div>
|
|
792
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
793
|
+
All States — Radio + Icon
|
|
794
|
+
</p>
|
|
335
795
|
<DropdownMenu>
|
|
336
796
|
<DropdownMenuTrigger asChild>
|
|
337
797
|
<ActionButton variant="icon">
|
|
338
798
|
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
339
799
|
</ActionButton>
|
|
340
800
|
</DropdownMenuTrigger>
|
|
801
|
+
<DropdownMenuContent
|
|
802
|
+
className="relative"
|
|
803
|
+
style={{ position: "static", transform: "none" }}
|
|
804
|
+
>
|
|
805
|
+
<DropdownMenuRadioGroup value="dark">
|
|
806
|
+
<DropdownMenuRadioItem
|
|
807
|
+
value="light"
|
|
808
|
+
icon={
|
|
809
|
+
<Icon
|
|
810
|
+
type="heroicons"
|
|
811
|
+
name="sun"
|
|
812
|
+
className="size-4 shrink-0"
|
|
813
|
+
/>
|
|
814
|
+
}
|
|
815
|
+
>
|
|
816
|
+
Light
|
|
817
|
+
</DropdownMenuRadioItem>
|
|
818
|
+
<DropdownMenuRadioItem
|
|
819
|
+
value="system"
|
|
820
|
+
className="!bg-[var(--dropdown-menu-hover-bg)]"
|
|
821
|
+
icon={
|
|
822
|
+
<Icon
|
|
823
|
+
type="heroicons"
|
|
824
|
+
name="computer-desktop"
|
|
825
|
+
className="size-4 shrink-0"
|
|
826
|
+
/>
|
|
827
|
+
}
|
|
828
|
+
>
|
|
829
|
+
System (Hover)
|
|
830
|
+
</DropdownMenuRadioItem>
|
|
831
|
+
<DropdownMenuRadioItem
|
|
832
|
+
value="dark"
|
|
833
|
+
icon={
|
|
834
|
+
<Icon
|
|
835
|
+
type="heroicons"
|
|
836
|
+
name="moon"
|
|
837
|
+
className="size-4 shrink-0"
|
|
838
|
+
/>
|
|
839
|
+
}
|
|
840
|
+
>
|
|
841
|
+
Dark (Selected)
|
|
842
|
+
</DropdownMenuRadioItem>
|
|
843
|
+
<DropdownMenuRadioItem
|
|
844
|
+
value="custom"
|
|
845
|
+
disabled
|
|
846
|
+
icon={
|
|
847
|
+
<Icon
|
|
848
|
+
type="heroicons"
|
|
849
|
+
name="paint-brush"
|
|
850
|
+
className="size-4 shrink-0"
|
|
851
|
+
/>
|
|
852
|
+
}
|
|
853
|
+
>
|
|
854
|
+
Custom (Disabled)
|
|
855
|
+
</DropdownMenuRadioItem>
|
|
856
|
+
<DropdownMenuRadioItem
|
|
857
|
+
value="dark"
|
|
858
|
+
disabled
|
|
859
|
+
icon={
|
|
860
|
+
<Icon
|
|
861
|
+
type="heroicons"
|
|
862
|
+
name="moon"
|
|
863
|
+
className="size-4 shrink-0"
|
|
864
|
+
/>
|
|
865
|
+
}
|
|
866
|
+
>
|
|
867
|
+
Dark (Selected + Disabled)
|
|
868
|
+
</DropdownMenuRadioItem>
|
|
869
|
+
</DropdownMenuRadioGroup>
|
|
870
|
+
</DropdownMenuContent>
|
|
871
|
+
</DropdownMenu>
|
|
872
|
+
</div>
|
|
873
|
+
|
|
874
|
+
<div>
|
|
875
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
876
|
+
Interactive
|
|
877
|
+
</p>
|
|
878
|
+
<DropdownMenu>
|
|
879
|
+
<DropdownMenuTrigger asChild>
|
|
880
|
+
<Button variant="outline">Theme: {theme}</Button>
|
|
881
|
+
</DropdownMenuTrigger>
|
|
341
882
|
<DropdownMenuContent>
|
|
342
|
-
<
|
|
343
|
-
<
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
883
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
884
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
885
|
+
<DropdownMenuRadioItem
|
|
886
|
+
value="light"
|
|
887
|
+
icon={
|
|
888
|
+
<Icon
|
|
889
|
+
type="heroicons"
|
|
890
|
+
name="sun"
|
|
891
|
+
className="size-4 shrink-0"
|
|
892
|
+
/>
|
|
893
|
+
}
|
|
894
|
+
>
|
|
895
|
+
Light
|
|
896
|
+
</DropdownMenuRadioItem>
|
|
897
|
+
<DropdownMenuRadioItem
|
|
898
|
+
value="dark"
|
|
899
|
+
icon={
|
|
900
|
+
<Icon
|
|
901
|
+
type="heroicons"
|
|
902
|
+
name="moon"
|
|
903
|
+
className="size-4 shrink-0"
|
|
904
|
+
/>
|
|
905
|
+
}
|
|
906
|
+
>
|
|
907
|
+
Dark
|
|
908
|
+
</DropdownMenuRadioItem>
|
|
909
|
+
<DropdownMenuRadioItem
|
|
910
|
+
value="system"
|
|
911
|
+
icon={
|
|
912
|
+
<Icon
|
|
913
|
+
type="heroicons"
|
|
914
|
+
name="computer-desktop"
|
|
915
|
+
className="size-4 shrink-0"
|
|
916
|
+
/>
|
|
917
|
+
}
|
|
918
|
+
>
|
|
919
|
+
System
|
|
920
|
+
</DropdownMenuRadioItem>
|
|
921
|
+
<DropdownMenuRadioItem
|
|
922
|
+
value="custom"
|
|
923
|
+
disabled
|
|
924
|
+
icon={
|
|
925
|
+
<Icon
|
|
926
|
+
type="heroicons"
|
|
927
|
+
name="paint-brush"
|
|
928
|
+
className="size-4"
|
|
929
|
+
/>
|
|
930
|
+
}
|
|
931
|
+
>
|
|
932
|
+
Custom
|
|
933
|
+
</DropdownMenuRadioItem>
|
|
934
|
+
</DropdownMenuRadioGroup>
|
|
347
935
|
</DropdownMenuContent>
|
|
348
936
|
</DropdownMenu>
|
|
349
937
|
</div>
|
|
@@ -352,21 +940,230 @@ export const AsChild = {
|
|
|
352
940
|
},
|
|
353
941
|
} satisfies StoryObj;
|
|
354
942
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
943
|
+
// ---------------------------------------------------------------------------
|
|
944
|
+
// DropdownMenuShortcut — keyboard shortcut label on the right side of item
|
|
945
|
+
// ---------------------------------------------------------------------------
|
|
946
|
+
export const WithShortcut = {
|
|
947
|
+
name: "With Shortcut",
|
|
948
|
+
render: () => (
|
|
949
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
950
|
+
<div>
|
|
951
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
952
|
+
All States — Shortcut
|
|
953
|
+
</p>
|
|
954
|
+
<DropdownMenu>
|
|
955
|
+
<DropdownMenuTrigger asChild>
|
|
956
|
+
<ActionButton variant="icon">
|
|
957
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
958
|
+
</ActionButton>
|
|
959
|
+
</DropdownMenuTrigger>
|
|
960
|
+
<DropdownMenuContent
|
|
961
|
+
className="relative"
|
|
962
|
+
style={{ position: "static", transform: "none" }}
|
|
963
|
+
>
|
|
964
|
+
<DropdownMenuItem>
|
|
965
|
+
New Tab
|
|
966
|
+
<DropdownMenuShortcut>⌘T</DropdownMenuShortcut>
|
|
967
|
+
</DropdownMenuItem>
|
|
968
|
+
<DropdownMenuItem className="!bg-[var(--dropdown-menu-hover-bg)]">
|
|
969
|
+
New Window (Hover)
|
|
970
|
+
<DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
|
|
971
|
+
</DropdownMenuItem>
|
|
972
|
+
<DropdownMenuSeparator />
|
|
973
|
+
<DropdownMenuItem>
|
|
974
|
+
<Icon
|
|
975
|
+
type="heroicons"
|
|
976
|
+
name="pencil"
|
|
977
|
+
className="size-4 shrink-0"
|
|
978
|
+
/>
|
|
979
|
+
Edit
|
|
980
|
+
<DropdownMenuShortcut>⌘E</DropdownMenuShortcut>
|
|
981
|
+
</DropdownMenuItem>
|
|
982
|
+
<DropdownMenuItem>
|
|
983
|
+
<Icon
|
|
984
|
+
type="heroicons"
|
|
985
|
+
name="document-duplicate"
|
|
986
|
+
className="size-4 shrink-0"
|
|
987
|
+
/>
|
|
988
|
+
Duplicate
|
|
989
|
+
<DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
|
|
990
|
+
</DropdownMenuItem>
|
|
991
|
+
<DropdownMenuSeparator />
|
|
992
|
+
<DropdownMenuItem disabled>
|
|
993
|
+
<Icon type="heroicons" name="trash" className="size-4 shrink-0" />
|
|
994
|
+
Delete
|
|
995
|
+
<DropdownMenuShortcut>⌫</DropdownMenuShortcut>
|
|
996
|
+
</DropdownMenuItem>
|
|
997
|
+
</DropdownMenuContent>
|
|
998
|
+
</DropdownMenu>
|
|
999
|
+
</div>
|
|
1000
|
+
|
|
1001
|
+
<div>
|
|
1002
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1003
|
+
Interactive
|
|
1004
|
+
</p>
|
|
1005
|
+
<DropdownMenu>
|
|
1006
|
+
<DropdownMenuTrigger asChild>
|
|
1007
|
+
<Button variant="outline">Open Menu</Button>
|
|
1008
|
+
</DropdownMenuTrigger>
|
|
1009
|
+
<DropdownMenuContent className="w-52">
|
|
1010
|
+
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
|
1011
|
+
<DropdownMenuSeparator />
|
|
1012
|
+
<DropdownMenuItem>
|
|
1013
|
+
New Tab
|
|
1014
|
+
<DropdownMenuShortcut>⌘T</DropdownMenuShortcut>
|
|
1015
|
+
</DropdownMenuItem>
|
|
1016
|
+
<DropdownMenuItem>
|
|
1017
|
+
New Window
|
|
1018
|
+
<DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
|
|
1019
|
+
</DropdownMenuItem>
|
|
1020
|
+
<DropdownMenuSeparator />
|
|
1021
|
+
<DropdownMenuItem>
|
|
1022
|
+
<Icon
|
|
1023
|
+
type="heroicons"
|
|
1024
|
+
name="pencil"
|
|
1025
|
+
className="size-4 shrink-0"
|
|
1026
|
+
/>
|
|
1027
|
+
Edit
|
|
1028
|
+
<DropdownMenuShortcut>⌘E</DropdownMenuShortcut>
|
|
1029
|
+
</DropdownMenuItem>
|
|
1030
|
+
<DropdownMenuItem>
|
|
1031
|
+
<Icon
|
|
1032
|
+
type="heroicons"
|
|
1033
|
+
name="document-duplicate"
|
|
1034
|
+
className="size-4 shrink-0"
|
|
1035
|
+
/>
|
|
1036
|
+
Duplicate
|
|
1037
|
+
<DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
|
|
1038
|
+
</DropdownMenuItem>
|
|
1039
|
+
<DropdownMenuSeparator />
|
|
1040
|
+
<DropdownMenuItem disabled>
|
|
1041
|
+
<Icon type="heroicons" name="trash" className="size-4 shrink-0" />
|
|
1042
|
+
Delete
|
|
1043
|
+
<DropdownMenuShortcut>⌫</DropdownMenuShortcut>
|
|
1044
|
+
</DropdownMenuItem>
|
|
1045
|
+
</DropdownMenuContent>
|
|
1046
|
+
</DropdownMenu>
|
|
1047
|
+
</div>
|
|
1048
|
+
</div>
|
|
1049
|
+
),
|
|
1050
|
+
} satisfies StoryObj;
|
|
1051
|
+
|
|
1052
|
+
// ---------------------------------------------------------------------------
|
|
1053
|
+
// Trigger variants (on icon button, etc.)
|
|
1054
|
+
// ---------------------------------------------------------------------------
|
|
1055
|
+
export const TriggerVariants = {
|
|
1056
|
+
name: "Trigger Variants",
|
|
1057
|
+
render: () => (
|
|
1058
|
+
<div className="flex gap-8 items-center flex-wrap">
|
|
1059
|
+
<div>
|
|
1060
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1061
|
+
Text Trigger
|
|
1062
|
+
</p>
|
|
1063
|
+
<DropdownMenu>
|
|
1064
|
+
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
1065
|
+
<DropdownMenuContent>
|
|
1066
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1067
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1068
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1069
|
+
</DropdownMenuContent>
|
|
1070
|
+
</DropdownMenu>
|
|
1071
|
+
</div>
|
|
1072
|
+
|
|
1073
|
+
<div>
|
|
1074
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1075
|
+
Button Trigger
|
|
1076
|
+
</p>
|
|
1077
|
+
<DropdownMenu>
|
|
1078
|
+
<DropdownMenuTrigger asChild>
|
|
1079
|
+
<Button variant="outline">Open Menu</Button>
|
|
1080
|
+
</DropdownMenuTrigger>
|
|
1081
|
+
<DropdownMenuContent>
|
|
1082
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1083
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1084
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1085
|
+
</DropdownMenuContent>
|
|
1086
|
+
</DropdownMenu>
|
|
1087
|
+
</div>
|
|
1088
|
+
|
|
1089
|
+
<div>
|
|
1090
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1091
|
+
Icon Button Trigger
|
|
1092
|
+
</p>
|
|
1093
|
+
<DropdownMenu>
|
|
1094
|
+
<DropdownMenuTrigger asChild>
|
|
1095
|
+
<ActionButton variant="icon">
|
|
1096
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
1097
|
+
</ActionButton>
|
|
1098
|
+
</DropdownMenuTrigger>
|
|
1099
|
+
<DropdownMenuContent>
|
|
1100
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1101
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1102
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
1103
|
+
</DropdownMenuContent>
|
|
1104
|
+
</DropdownMenu>
|
|
1105
|
+
</div>
|
|
1106
|
+
|
|
1107
|
+
<div>
|
|
1108
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1109
|
+
Horizontal dots
|
|
1110
|
+
</p>
|
|
1111
|
+
<DropdownMenu>
|
|
1112
|
+
<DropdownMenuTrigger asChild>
|
|
1113
|
+
<ActionButton variant="icon">
|
|
1114
|
+
<Icon type="heroicons" name="ellipsis-horizontal" />
|
|
1115
|
+
</ActionButton>
|
|
1116
|
+
</DropdownMenuTrigger>
|
|
1117
|
+
<DropdownMenuContent>
|
|
1118
|
+
<DropdownMenuItem>
|
|
1119
|
+
<Icon
|
|
1120
|
+
type="heroicons"
|
|
1121
|
+
name="pencil"
|
|
1122
|
+
className="size-4 shrink-0"
|
|
1123
|
+
/>
|
|
1124
|
+
Edit
|
|
1125
|
+
</DropdownMenuItem>
|
|
1126
|
+
<DropdownMenuItem>
|
|
1127
|
+
<Icon
|
|
1128
|
+
type="heroicons"
|
|
1129
|
+
name="document-duplicate"
|
|
1130
|
+
className="size-4 shrink-0"
|
|
1131
|
+
/>
|
|
1132
|
+
Duplicate
|
|
1133
|
+
</DropdownMenuItem>
|
|
1134
|
+
<DropdownMenuSeparator />
|
|
1135
|
+
<DropdownMenuItem disabled>
|
|
1136
|
+
<Icon type="heroicons" name="trash" className="size-4 shrink-0" />
|
|
1137
|
+
Delete
|
|
1138
|
+
</DropdownMenuItem>
|
|
1139
|
+
</DropdownMenuContent>
|
|
1140
|
+
</DropdownMenu>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
),
|
|
1144
|
+
} satisfies StoryObj;
|
|
1145
|
+
|
|
1146
|
+
// ---------------------------------------------------------------------------
|
|
1147
|
+
// Complex showcase — real-world patterns combining all item types
|
|
1148
|
+
// ---------------------------------------------------------------------------
|
|
1149
|
+
export const ComplexShowcase = {
|
|
1150
|
+
name: "Complex Showcase",
|
|
1151
|
+
render: () => {
|
|
1152
|
+
const [theme, setTheme] = useState("dark");
|
|
1153
|
+
const [density, setDensity] = useState("comfortable");
|
|
1154
|
+
const [sortBy, setSortBy] = useState("name");
|
|
1155
|
+
const [sortDir, setSortDir] = useState("asc");
|
|
1156
|
+
const [showHidden, setShowHidden] = useState(false);
|
|
1157
|
+
const [showExtensions, setShowExtensions] = useState(true);
|
|
1158
|
+
const [showPreview, setShowPreview] = useState(true);
|
|
1159
|
+
|
|
367
1160
|
return (
|
|
368
|
-
<div className="flex
|
|
369
|
-
|
|
1161
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
1162
|
+
{/* Static: File manager — MenuItem + RadioGroup + CheckboxItem */}
|
|
1163
|
+
<div>
|
|
1164
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1165
|
+
File Manager Actions
|
|
1166
|
+
</p>
|
|
370
1167
|
<DropdownMenu>
|
|
371
1168
|
<DropdownMenuTrigger asChild>
|
|
372
1169
|
<ActionButton variant="icon">
|
|
@@ -374,17 +1171,342 @@ export const Position = {
|
|
|
374
1171
|
</ActionButton>
|
|
375
1172
|
</DropdownMenuTrigger>
|
|
376
1173
|
<DropdownMenuContent
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
align="start" // controls the alignment (start, center, end)
|
|
380
|
-
sideOffset={5} // offset from the side
|
|
381
|
-
alignOffset={0} // offset from the alignment
|
|
1174
|
+
className="relative w-[220px]"
|
|
1175
|
+
style={{ position: "static", transform: "none" }}
|
|
382
1176
|
>
|
|
383
|
-
<DropdownMenuItem
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
1177
|
+
<DropdownMenuItem
|
|
1178
|
+
icon={
|
|
1179
|
+
<Icon
|
|
1180
|
+
type="heroicons"
|
|
1181
|
+
name="pencil"
|
|
1182
|
+
className="size-4 shrink-0"
|
|
1183
|
+
/>
|
|
1184
|
+
}
|
|
1185
|
+
>
|
|
1186
|
+
Rename
|
|
1187
|
+
</DropdownMenuItem>
|
|
1188
|
+
<DropdownMenuItem
|
|
1189
|
+
icon={
|
|
1190
|
+
<Icon
|
|
1191
|
+
type="heroicons"
|
|
1192
|
+
name="document-duplicate"
|
|
1193
|
+
className="size-4 shrink-0"
|
|
1194
|
+
/>
|
|
1195
|
+
}
|
|
1196
|
+
>
|
|
1197
|
+
Duplicate
|
|
1198
|
+
</DropdownMenuItem>
|
|
1199
|
+
<DropdownMenuSeparator />
|
|
1200
|
+
<DropdownMenuLabel>Sort By</DropdownMenuLabel>
|
|
1201
|
+
<DropdownMenuRadioGroup value="name">
|
|
1202
|
+
<DropdownMenuRadioItem value="name">Name</DropdownMenuRadioItem>
|
|
1203
|
+
<DropdownMenuRadioItem value="date">
|
|
1204
|
+
Date Modified
|
|
1205
|
+
</DropdownMenuRadioItem>
|
|
1206
|
+
<DropdownMenuRadioItem value="size">Size</DropdownMenuRadioItem>
|
|
1207
|
+
</DropdownMenuRadioGroup>
|
|
1208
|
+
<DropdownMenuSeparator />
|
|
1209
|
+
<DropdownMenuLabel>Show</DropdownMenuLabel>
|
|
1210
|
+
<DropdownMenuCheckboxItem>Hidden Files</DropdownMenuCheckboxItem>
|
|
1211
|
+
<DropdownMenuCheckboxItem checked>
|
|
1212
|
+
File Extensions
|
|
1213
|
+
</DropdownMenuCheckboxItem>
|
|
1214
|
+
<DropdownMenuCheckboxItem checked>
|
|
1215
|
+
Preview Panel
|
|
1216
|
+
</DropdownMenuCheckboxItem>
|
|
1217
|
+
<DropdownMenuSeparator />
|
|
1218
|
+
<DropdownMenuItem
|
|
1219
|
+
disabled
|
|
1220
|
+
icon={
|
|
1221
|
+
<Icon
|
|
1222
|
+
type="heroicons"
|
|
1223
|
+
name="trash"
|
|
1224
|
+
className="size-4 shrink-0"
|
|
1225
|
+
/>
|
|
1226
|
+
}
|
|
1227
|
+
>
|
|
1228
|
+
Delete
|
|
1229
|
+
</DropdownMenuItem>
|
|
1230
|
+
</DropdownMenuContent>
|
|
1231
|
+
</DropdownMenu>
|
|
1232
|
+
</div>
|
|
1233
|
+
|
|
1234
|
+
{/* Static: Editor settings — multiple RadioGroups per section */}
|
|
1235
|
+
<div>
|
|
1236
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1237
|
+
Editor Settings (Multiple RadioGroups)
|
|
1238
|
+
</p>
|
|
1239
|
+
<DropdownMenu>
|
|
1240
|
+
<DropdownMenuTrigger asChild>
|
|
1241
|
+
<ActionButton variant="icon">
|
|
1242
|
+
<Icon type="heroicons" name="cog-6-tooth" />
|
|
1243
|
+
</ActionButton>
|
|
1244
|
+
</DropdownMenuTrigger>
|
|
1245
|
+
<DropdownMenuContent
|
|
1246
|
+
className="relative w-[220px]"
|
|
1247
|
+
style={{ position: "static", transform: "none" }}
|
|
1248
|
+
>
|
|
1249
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
1250
|
+
<DropdownMenuRadioGroup value="dark">
|
|
1251
|
+
<DropdownMenuRadioItem
|
|
1252
|
+
value="light"
|
|
1253
|
+
icon={
|
|
1254
|
+
<Icon
|
|
1255
|
+
type="heroicons"
|
|
1256
|
+
name="sun"
|
|
1257
|
+
className="size-4 shrink-0"
|
|
1258
|
+
/>
|
|
1259
|
+
}
|
|
1260
|
+
>
|
|
1261
|
+
Light
|
|
1262
|
+
</DropdownMenuRadioItem>
|
|
1263
|
+
<DropdownMenuRadioItem
|
|
1264
|
+
value="dark"
|
|
1265
|
+
icon={
|
|
1266
|
+
<Icon
|
|
1267
|
+
type="heroicons"
|
|
1268
|
+
name="moon"
|
|
1269
|
+
className="size-4 shrink-0"
|
|
1270
|
+
/>
|
|
1271
|
+
}
|
|
1272
|
+
>
|
|
1273
|
+
Dark
|
|
1274
|
+
</DropdownMenuRadioItem>
|
|
1275
|
+
<DropdownMenuRadioItem
|
|
1276
|
+
value="system"
|
|
1277
|
+
icon={
|
|
1278
|
+
<Icon
|
|
1279
|
+
type="heroicons"
|
|
1280
|
+
name="computer-desktop"
|
|
1281
|
+
className="size-4 shrink-0"
|
|
1282
|
+
/>
|
|
1283
|
+
}
|
|
1284
|
+
>
|
|
1285
|
+
System
|
|
1286
|
+
</DropdownMenuRadioItem>
|
|
1287
|
+
</DropdownMenuRadioGroup>
|
|
1288
|
+
<DropdownMenuSeparator />
|
|
1289
|
+
<DropdownMenuLabel>Density</DropdownMenuLabel>
|
|
1290
|
+
<DropdownMenuRadioGroup value="comfortable">
|
|
1291
|
+
<DropdownMenuRadioItem value="compact">
|
|
1292
|
+
Compact
|
|
1293
|
+
</DropdownMenuRadioItem>
|
|
1294
|
+
<DropdownMenuRadioItem value="comfortable">
|
|
1295
|
+
Comfortable
|
|
1296
|
+
</DropdownMenuRadioItem>
|
|
1297
|
+
<DropdownMenuRadioItem value="spacious">
|
|
1298
|
+
Spacious
|
|
1299
|
+
</DropdownMenuRadioItem>
|
|
1300
|
+
</DropdownMenuRadioGroup>
|
|
1301
|
+
<DropdownMenuSeparator />
|
|
1302
|
+
<DropdownMenuLabel>Sort Direction</DropdownMenuLabel>
|
|
1303
|
+
<DropdownMenuRadioGroup value="asc">
|
|
1304
|
+
<DropdownMenuRadioItem
|
|
1305
|
+
value="asc"
|
|
1306
|
+
icon={
|
|
1307
|
+
<Icon
|
|
1308
|
+
type="heroicons"
|
|
1309
|
+
name="bars-arrow-up"
|
|
1310
|
+
className="size-4 shrink-0"
|
|
1311
|
+
/>
|
|
1312
|
+
}
|
|
1313
|
+
>
|
|
1314
|
+
Ascending
|
|
1315
|
+
</DropdownMenuRadioItem>
|
|
1316
|
+
<DropdownMenuRadioItem
|
|
1317
|
+
value="desc"
|
|
1318
|
+
icon={
|
|
1319
|
+
<Icon
|
|
1320
|
+
type="heroicons"
|
|
1321
|
+
name="bars-arrow-down"
|
|
1322
|
+
className="size-4 shrink-0"
|
|
1323
|
+
/>
|
|
1324
|
+
}
|
|
1325
|
+
>
|
|
1326
|
+
Descending
|
|
1327
|
+
</DropdownMenuRadioItem>
|
|
1328
|
+
</DropdownMenuRadioGroup>
|
|
1329
|
+
</DropdownMenuContent>
|
|
1330
|
+
</DropdownMenu>
|
|
1331
|
+
</div>
|
|
1332
|
+
|
|
1333
|
+
{/* Interactive: File Manager */}
|
|
1334
|
+
<div>
|
|
1335
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1336
|
+
Interactive — File Manager
|
|
1337
|
+
</p>
|
|
1338
|
+
<DropdownMenu>
|
|
1339
|
+
<DropdownMenuTrigger asChild>
|
|
1340
|
+
<Button variant="outline">Options</Button>
|
|
1341
|
+
</DropdownMenuTrigger>
|
|
1342
|
+
<DropdownMenuContent className="w-[220px]">
|
|
1343
|
+
<DropdownMenuItem
|
|
1344
|
+
icon={
|
|
1345
|
+
<Icon
|
|
1346
|
+
type="heroicons"
|
|
1347
|
+
name="pencil"
|
|
1348
|
+
className="size-4 shrink-0"
|
|
1349
|
+
/>
|
|
1350
|
+
}
|
|
1351
|
+
>
|
|
1352
|
+
Rename
|
|
1353
|
+
</DropdownMenuItem>
|
|
1354
|
+
<DropdownMenuItem
|
|
1355
|
+
icon={
|
|
1356
|
+
<Icon
|
|
1357
|
+
type="heroicons"
|
|
1358
|
+
name="document-duplicate"
|
|
1359
|
+
className="size-4 shrink-0"
|
|
1360
|
+
/>
|
|
1361
|
+
}
|
|
1362
|
+
>
|
|
1363
|
+
Duplicate
|
|
1364
|
+
</DropdownMenuItem>
|
|
1365
|
+
<DropdownMenuSeparator />
|
|
1366
|
+
<DropdownMenuLabel>Sort By</DropdownMenuLabel>
|
|
1367
|
+
<DropdownMenuRadioGroup value={sortBy} onValueChange={setSortBy}>
|
|
1368
|
+
<DropdownMenuRadioItem value="name">Name</DropdownMenuRadioItem>
|
|
1369
|
+
<DropdownMenuRadioItem value="date">
|
|
1370
|
+
Date Modified
|
|
1371
|
+
</DropdownMenuRadioItem>
|
|
1372
|
+
<DropdownMenuRadioItem value="size">Size</DropdownMenuRadioItem>
|
|
1373
|
+
</DropdownMenuRadioGroup>
|
|
1374
|
+
<DropdownMenuSeparator />
|
|
1375
|
+
<DropdownMenuLabel>Show</DropdownMenuLabel>
|
|
1376
|
+
<DropdownMenuCheckboxItem
|
|
1377
|
+
checked={showHidden}
|
|
1378
|
+
onCheckedChange={setShowHidden}
|
|
1379
|
+
onSelect={(e) => e.preventDefault()}
|
|
1380
|
+
>
|
|
1381
|
+
Hidden Files
|
|
1382
|
+
</DropdownMenuCheckboxItem>
|
|
1383
|
+
<DropdownMenuCheckboxItem
|
|
1384
|
+
checked={showExtensions}
|
|
1385
|
+
onCheckedChange={setShowExtensions}
|
|
1386
|
+
onSelect={(e) => e.preventDefault()}
|
|
1387
|
+
>
|
|
1388
|
+
File Extensions
|
|
1389
|
+
</DropdownMenuCheckboxItem>
|
|
1390
|
+
<DropdownMenuCheckboxItem
|
|
1391
|
+
checked={showPreview}
|
|
1392
|
+
onCheckedChange={setShowPreview}
|
|
1393
|
+
onSelect={(e) => e.preventDefault()}
|
|
1394
|
+
>
|
|
1395
|
+
Preview Panel
|
|
1396
|
+
</DropdownMenuCheckboxItem>
|
|
1397
|
+
<DropdownMenuSeparator />
|
|
1398
|
+
<DropdownMenuItem
|
|
1399
|
+
disabled
|
|
1400
|
+
icon={
|
|
1401
|
+
<Icon
|
|
1402
|
+
type="heroicons"
|
|
1403
|
+
name="trash"
|
|
1404
|
+
className="size-4 shrink-0"
|
|
1405
|
+
/>
|
|
1406
|
+
}
|
|
1407
|
+
>
|
|
1408
|
+
Delete
|
|
1409
|
+
</DropdownMenuItem>
|
|
1410
|
+
</DropdownMenuContent>
|
|
1411
|
+
</DropdownMenu>
|
|
1412
|
+
</div>
|
|
1413
|
+
|
|
1414
|
+
{/* Interactive: Editor Settings */}
|
|
1415
|
+
<div>
|
|
1416
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">
|
|
1417
|
+
Interactive — Editor Settings
|
|
1418
|
+
</p>
|
|
1419
|
+
<DropdownMenu>
|
|
1420
|
+
<DropdownMenuTrigger asChild>
|
|
1421
|
+
<Button variant="outline">Settings</Button>
|
|
1422
|
+
</DropdownMenuTrigger>
|
|
1423
|
+
<DropdownMenuContent className="w-[220px]">
|
|
1424
|
+
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
|
1425
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
1426
|
+
<DropdownMenuRadioItem
|
|
1427
|
+
value="light"
|
|
1428
|
+
icon={
|
|
1429
|
+
<Icon
|
|
1430
|
+
type="heroicons"
|
|
1431
|
+
name="sun"
|
|
1432
|
+
className="size-4 shrink-0"
|
|
1433
|
+
/>
|
|
1434
|
+
}
|
|
1435
|
+
>
|
|
1436
|
+
Light
|
|
1437
|
+
</DropdownMenuRadioItem>
|
|
1438
|
+
<DropdownMenuRadioItem
|
|
1439
|
+
value="dark"
|
|
1440
|
+
icon={
|
|
1441
|
+
<Icon
|
|
1442
|
+
type="heroicons"
|
|
1443
|
+
name="moon"
|
|
1444
|
+
className="size-4 shrink-0"
|
|
1445
|
+
/>
|
|
1446
|
+
}
|
|
1447
|
+
>
|
|
1448
|
+
Dark
|
|
1449
|
+
</DropdownMenuRadioItem>
|
|
1450
|
+
<DropdownMenuRadioItem
|
|
1451
|
+
value="system"
|
|
1452
|
+
icon={
|
|
1453
|
+
<Icon
|
|
1454
|
+
type="heroicons"
|
|
1455
|
+
name="computer-desktop"
|
|
1456
|
+
className="size-4 shrink-0"
|
|
1457
|
+
/>
|
|
1458
|
+
}
|
|
1459
|
+
>
|
|
1460
|
+
System
|
|
1461
|
+
</DropdownMenuRadioItem>
|
|
1462
|
+
</DropdownMenuRadioGroup>
|
|
1463
|
+
<DropdownMenuSeparator />
|
|
1464
|
+
<DropdownMenuLabel>Density</DropdownMenuLabel>
|
|
1465
|
+
<DropdownMenuRadioGroup
|
|
1466
|
+
value={density}
|
|
1467
|
+
onValueChange={setDensity}
|
|
1468
|
+
>
|
|
1469
|
+
<DropdownMenuRadioItem value="compact">
|
|
1470
|
+
Compact
|
|
1471
|
+
</DropdownMenuRadioItem>
|
|
1472
|
+
<DropdownMenuRadioItem value="comfortable">
|
|
1473
|
+
Comfortable
|
|
1474
|
+
</DropdownMenuRadioItem>
|
|
1475
|
+
<DropdownMenuRadioItem value="spacious">
|
|
1476
|
+
Spacious
|
|
1477
|
+
</DropdownMenuRadioItem>
|
|
1478
|
+
</DropdownMenuRadioGroup>
|
|
1479
|
+
<DropdownMenuSeparator />
|
|
1480
|
+
<DropdownMenuLabel>Sort Direction</DropdownMenuLabel>
|
|
1481
|
+
<DropdownMenuRadioGroup
|
|
1482
|
+
value={sortDir}
|
|
1483
|
+
onValueChange={setSortDir}
|
|
1484
|
+
>
|
|
1485
|
+
<DropdownMenuRadioItem
|
|
1486
|
+
value="asc"
|
|
1487
|
+
icon={
|
|
1488
|
+
<Icon
|
|
1489
|
+
type="heroicons"
|
|
1490
|
+
name="bars-arrow-up"
|
|
1491
|
+
className="size-4 shrink-0"
|
|
1492
|
+
/>
|
|
1493
|
+
}
|
|
1494
|
+
>
|
|
1495
|
+
Ascending
|
|
1496
|
+
</DropdownMenuRadioItem>
|
|
1497
|
+
<DropdownMenuRadioItem
|
|
1498
|
+
value="desc"
|
|
1499
|
+
icon={
|
|
1500
|
+
<Icon
|
|
1501
|
+
type="heroicons"
|
|
1502
|
+
name="bars-arrow-down"
|
|
1503
|
+
className="size-4 shrink-0"
|
|
1504
|
+
/>
|
|
1505
|
+
}
|
|
1506
|
+
>
|
|
1507
|
+
Descending
|
|
1508
|
+
</DropdownMenuRadioItem>
|
|
1509
|
+
</DropdownMenuRadioGroup>
|
|
388
1510
|
</DropdownMenuContent>
|
|
389
1511
|
</DropdownMenu>
|
|
390
1512
|
</div>
|