@rovula/ui 0.1.18 → 0.1.21
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 +141 -17
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.stories.d.ts +29 -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 +1 -0
- package/dist/cjs/types/patterns/confirm-dialog/ConfirmDialog.d.ts +1 -0
- package/dist/cjs/types/patterns/confirm-dialog/ConfirmDialog.stories.d.ts +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +7 -9
- package/dist/components/DropdownMenu/DropdownMenu.stories.js +79 -91
- 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/esm/bundle.css +141 -17
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.stories.d.ts +29 -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 +1 -0
- package/dist/esm/types/patterns/confirm-dialog/ConfirmDialog.d.ts +1 -0
- package/dist/esm/types/patterns/confirm-dialog/ConfirmDialog.stories.d.ts +1 -0
- package/dist/index.d.ts +42 -2
- package/dist/index.js +1 -0
- package/dist/patterns/confirm-dialog/ConfirmDialog.js +2 -2
- package/dist/patterns/form-dialog/FormDialog.js +1 -1
- package/dist/src/theme/global.css +196 -20
- package/package.json +1 -1
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +482 -297
- package/src/components/DropdownMenu/DropdownMenu.tsx +7 -8
- 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/index.ts +1 -0
- package/src/patterns/confirm-dialog/ConfirmDialog.tsx +4 -0
- package/src/patterns/form-dialog/FormDialog.tsx +5 -1
- package/src/theme/global.css +84 -11
- package/src/theme/themes/xspector/baseline.css +1 -0
- package/src/theme/themes/xspector/components/dropdown-menu.css +2 -2
- package/src/theme/themes/xspector/components/scrollbar.css +12 -0
- package/src/theme/tokens/baseline.css +2 -1
- package/src/theme/tokens/components/dropdown-menu.css +1 -1
- package/src/theme/tokens/components/scrollbar.css +18 -0
|
@@ -15,20 +15,19 @@ import {
|
|
|
15
15
|
DropdownMenuTrigger,
|
|
16
16
|
} from "./DropdownMenu";
|
|
17
17
|
import Button from "../Button/Button";
|
|
18
|
-
import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu";
|
|
19
|
-
import Icon from "../Icon/Icon";
|
|
20
18
|
import ActionButton from "../ActionButton/ActionButton";
|
|
19
|
+
import Icon from "../Icon/Icon";
|
|
20
|
+
import { Input } from "../Input/Input";
|
|
21
21
|
|
|
22
22
|
const meta = {
|
|
23
23
|
title: "Components/DropdownMenu",
|
|
24
24
|
component: DropdownMenu,
|
|
25
|
-
// tags: ["autodocs"],
|
|
26
25
|
parameters: {
|
|
27
26
|
layout: "fullscreen",
|
|
28
27
|
},
|
|
29
28
|
decorators: [
|
|
30
29
|
(Story) => (
|
|
31
|
-
<div className="p-
|
|
30
|
+
<div className="p-10 flex gap-8 flex-wrap bg-workspace-surface min-h-screen">
|
|
32
31
|
<Story />
|
|
33
32
|
</div>
|
|
34
33
|
),
|
|
@@ -37,193 +36,171 @@ const meta = {
|
|
|
37
36
|
|
|
38
37
|
export default meta;
|
|
39
38
|
|
|
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
|
-
</DropdownMenuContent>
|
|
66
|
-
</DropdownMenu>
|
|
67
|
-
</div>
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Figma: Normal dropdown / action menu
|
|
41
|
+
// Shows all item states: Default, Hover (focus), Selected, Disabled, Selected+Disabled
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
export const AllStates = {
|
|
44
|
+
name: "All States (Normal)",
|
|
45
|
+
render: () => (
|
|
46
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
47
|
+
{/* Default open — all states visible */}
|
|
48
|
+
<div>
|
|
49
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">All States</p>
|
|
50
|
+
<DropdownMenu open>
|
|
51
|
+
<DropdownMenuTrigger asChild>
|
|
52
|
+
<ActionButton variant="icon">
|
|
53
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
54
|
+
</ActionButton>
|
|
55
|
+
</DropdownMenuTrigger>
|
|
56
|
+
<DropdownMenuContent className="relative" style={{ position: "static", transform: "none" }}>
|
|
57
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
58
|
+
<DropdownMenuItem className="!bg-[var(--dropdown-menu-hover-bg)]">Option Description (Hover)</DropdownMenuItem>
|
|
59
|
+
<DropdownMenuCheckboxItem checked>Option Description</DropdownMenuCheckboxItem>
|
|
60
|
+
<DropdownMenuItem disabled>Option Description</DropdownMenuItem>
|
|
61
|
+
<DropdownMenuCheckboxItem checked disabled>Option Description</DropdownMenuCheckboxItem>
|
|
62
|
+
</DropdownMenuContent>
|
|
63
|
+
</DropdownMenu>
|
|
68
64
|
</div>
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
|
|
66
|
+
{/* Interactive version */}
|
|
67
|
+
<div>
|
|
68
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
69
|
+
<DropdownMenu>
|
|
70
|
+
<DropdownMenuTrigger asChild>
|
|
71
|
+
<Button variant="outline">Open Menu</Button>
|
|
72
|
+
</DropdownMenuTrigger>
|
|
73
|
+
<DropdownMenuContent>
|
|
74
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
75
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
76
|
+
<DropdownMenuCheckboxItem checked>Option Description</DropdownMenuCheckboxItem>
|
|
77
|
+
<DropdownMenuItem disabled>Option Description</DropdownMenuItem>
|
|
78
|
+
<DropdownMenuCheckboxItem checked disabled>Option Description</DropdownMenuCheckboxItem>
|
|
79
|
+
</DropdownMenuContent>
|
|
80
|
+
</DropdownMenu>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
),
|
|
71
84
|
} satisfies StoryObj;
|
|
72
85
|
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Figma: Have icon
|
|
88
|
+
// Items with leading icon
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
73
90
|
export const WithIcon = {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
<DropdownMenuItem disabled>
|
|
109
|
-
<Icon
|
|
110
|
-
type="heroicons"
|
|
111
|
-
name="rocket-launch"
|
|
112
|
-
className="size-4"
|
|
113
|
-
/>
|
|
114
|
-
<span>Option Description</span>
|
|
115
|
-
</DropdownMenuItem>
|
|
116
|
-
</DropdownMenuContent>
|
|
117
|
-
</DropdownMenu>
|
|
118
|
-
</div>
|
|
91
|
+
name: "With Icon",
|
|
92
|
+
render: () => (
|
|
93
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
94
|
+
<div>
|
|
95
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">All States — With Icon</p>
|
|
96
|
+
<DropdownMenu open>
|
|
97
|
+
<DropdownMenuTrigger asChild>
|
|
98
|
+
<ActionButton variant="icon">
|
|
99
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
100
|
+
</ActionButton>
|
|
101
|
+
</DropdownMenuTrigger>
|
|
102
|
+
<DropdownMenuContent className="relative" style={{ position: "static", transform: "none" }}>
|
|
103
|
+
<DropdownMenuItem>
|
|
104
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
105
|
+
Option Description
|
|
106
|
+
</DropdownMenuItem>
|
|
107
|
+
<DropdownMenuItem className="!bg-[var(--dropdown-menu-hover-bg)]">
|
|
108
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
109
|
+
Option Description (Hover)
|
|
110
|
+
</DropdownMenuItem>
|
|
111
|
+
<DropdownMenuCheckboxItem checked>
|
|
112
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
113
|
+
Option Description
|
|
114
|
+
</DropdownMenuCheckboxItem>
|
|
115
|
+
<DropdownMenuItem disabled>
|
|
116
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
117
|
+
Option Description
|
|
118
|
+
</DropdownMenuItem>
|
|
119
|
+
<DropdownMenuCheckboxItem checked disabled>
|
|
120
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
121
|
+
Option Description
|
|
122
|
+
</DropdownMenuCheckboxItem>
|
|
123
|
+
</DropdownMenuContent>
|
|
124
|
+
</DropdownMenu>
|
|
119
125
|
</div>
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
|
|
127
|
+
<div>
|
|
128
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
129
|
+
<DropdownMenu>
|
|
130
|
+
<DropdownMenuTrigger asChild>
|
|
131
|
+
<Button variant="outline">Open Menu</Button>
|
|
132
|
+
</DropdownMenuTrigger>
|
|
133
|
+
<DropdownMenuContent>
|
|
134
|
+
<DropdownMenuItem>
|
|
135
|
+
<Icon type="heroicons" name="rocket-launch" className="size-4 shrink-0" />
|
|
136
|
+
Option Description
|
|
137
|
+
</DropdownMenuItem>
|
|
138
|
+
<DropdownMenuItem>
|
|
139
|
+
<Icon type="heroicons" name="pencil" className="size-4 shrink-0" />
|
|
140
|
+
Option Description
|
|
141
|
+
</DropdownMenuItem>
|
|
142
|
+
<DropdownMenuItem>
|
|
143
|
+
<Icon type="heroicons" name="trash" className="size-4 shrink-0" />
|
|
144
|
+
Option Description
|
|
145
|
+
</DropdownMenuItem>
|
|
146
|
+
<DropdownMenuItem disabled>
|
|
147
|
+
<Icon type="heroicons" name="arrow-path" className="size-4 shrink-0" />
|
|
148
|
+
Option Description
|
|
149
|
+
</DropdownMenuItem>
|
|
150
|
+
</DropdownMenuContent>
|
|
151
|
+
</DropdownMenu>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
),
|
|
122
155
|
} satisfies StoryObj;
|
|
123
156
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
};
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Figma: Checkbox items (Have icon=No, Checkbox=Yes)
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
export const WithCheckbox = {
|
|
161
|
+
name: "With Checkbox",
|
|
162
|
+
render: () => {
|
|
163
|
+
const [checked1, setChecked1] = useState(false);
|
|
164
|
+
const [checked2, setChecked2] = useState(true);
|
|
165
|
+
const [checked3, setChecked3] = useState(false);
|
|
166
|
+
|
|
135
167
|
return (
|
|
136
|
-
<div className="flex
|
|
137
|
-
<div
|
|
138
|
-
<
|
|
168
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
169
|
+
<div>
|
|
170
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">All States — Checkbox</p>
|
|
171
|
+
<DropdownMenu open>
|
|
139
172
|
<DropdownMenuTrigger asChild>
|
|
140
|
-
<
|
|
173
|
+
<ActionButton variant="icon">
|
|
174
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
175
|
+
</ActionButton>
|
|
141
176
|
</DropdownMenuTrigger>
|
|
142
|
-
<DropdownMenuContent>
|
|
143
|
-
<
|
|
144
|
-
<
|
|
145
|
-
<
|
|
146
|
-
<
|
|
147
|
-
<
|
|
148
|
-
<DropdownMenuSeparator />
|
|
149
|
-
<DropdownMenuLabel>Sort by</DropdownMenuLabel>
|
|
150
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
151
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
152
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
153
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
154
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
177
|
+
<DropdownMenuContent className="relative" style={{ position: "static", transform: "none" }}>
|
|
178
|
+
<DropdownMenuCheckboxItem>Option Description</DropdownMenuCheckboxItem>
|
|
179
|
+
<DropdownMenuCheckboxItem className="!bg-[var(--dropdown-menu-hover-bg)]">Option Description (Hover)</DropdownMenuCheckboxItem>
|
|
180
|
+
<DropdownMenuCheckboxItem checked>Option Description</DropdownMenuCheckboxItem>
|
|
181
|
+
<DropdownMenuCheckboxItem disabled>Option Description</DropdownMenuCheckboxItem>
|
|
182
|
+
<DropdownMenuCheckboxItem checked disabled>Option Description</DropdownMenuCheckboxItem>
|
|
155
183
|
</DropdownMenuContent>
|
|
156
184
|
</DropdownMenu>
|
|
157
185
|
</div>
|
|
158
|
-
</div>
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
} satisfies StoryObj;
|
|
162
186
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// DropdownMenu: "Lorem Ipsum",
|
|
166
|
-
// value: "Lorem Ipsum",
|
|
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">
|
|
187
|
+
<div>
|
|
188
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
178
189
|
<DropdownMenu>
|
|
179
190
|
<DropdownMenuTrigger asChild>
|
|
180
|
-
<Button variant="outline">Open</Button>
|
|
191
|
+
<Button variant="outline">Open Menu</Button>
|
|
181
192
|
</DropdownMenuTrigger>
|
|
182
193
|
<DropdownMenuContent>
|
|
183
|
-
<DropdownMenuCheckboxItem>
|
|
184
|
-
Option Description
|
|
185
|
-
</DropdownMenuCheckboxItem>
|
|
186
|
-
<DropdownMenuCheckboxItem checked>
|
|
194
|
+
<DropdownMenuCheckboxItem checked={checked1} onCheckedChange={setChecked1}>
|
|
187
195
|
Option Description
|
|
188
196
|
</DropdownMenuCheckboxItem>
|
|
189
|
-
<DropdownMenuCheckboxItem
|
|
197
|
+
<DropdownMenuCheckboxItem checked={checked2} onCheckedChange={setChecked2}>
|
|
190
198
|
Option Description
|
|
191
199
|
</DropdownMenuCheckboxItem>
|
|
192
|
-
<DropdownMenuCheckboxItem checked
|
|
200
|
+
<DropdownMenuCheckboxItem checked={checked3} onCheckedChange={setChecked3}>
|
|
193
201
|
Option Description
|
|
194
202
|
</DropdownMenuCheckboxItem>
|
|
195
|
-
<DropdownMenuCheckboxItem>
|
|
196
|
-
<Icon
|
|
197
|
-
type="heroicons"
|
|
198
|
-
name="rocket-launch"
|
|
199
|
-
className="size-4"
|
|
200
|
-
/>
|
|
201
|
-
<span>Option Description</span>
|
|
202
|
-
</DropdownMenuCheckboxItem>
|
|
203
|
-
<DropdownMenuCheckboxItem checked>
|
|
204
|
-
<Icon
|
|
205
|
-
type="heroicons"
|
|
206
|
-
name="rocket-launch"
|
|
207
|
-
className="size-4"
|
|
208
|
-
/>
|
|
209
|
-
<span>Option Description</span>
|
|
210
|
-
</DropdownMenuCheckboxItem>
|
|
211
|
-
<DropdownMenuCheckboxItem disabled>
|
|
212
|
-
<Icon
|
|
213
|
-
type="heroicons"
|
|
214
|
-
name="rocket-launch"
|
|
215
|
-
className="size-4"
|
|
216
|
-
/>
|
|
217
|
-
<span>Option Description</span>
|
|
218
|
-
</DropdownMenuCheckboxItem>
|
|
219
|
-
<DropdownMenuCheckboxItem checked disabled>
|
|
220
|
-
<Icon
|
|
221
|
-
type="heroicons"
|
|
222
|
-
name="rocket-launch"
|
|
223
|
-
className="size-4"
|
|
224
|
-
/>
|
|
225
|
-
<span>Option Description</span>
|
|
226
|
-
</DropdownMenuCheckboxItem>
|
|
203
|
+
<DropdownMenuCheckboxItem disabled>Option Description</DropdownMenuCheckboxItem>
|
|
227
204
|
</DropdownMenuContent>
|
|
228
205
|
</DropdownMenu>
|
|
229
206
|
</div>
|
|
@@ -232,154 +209,139 @@ export const Checkboxes = {
|
|
|
232
209
|
},
|
|
233
210
|
} satisfies StoryObj;
|
|
234
211
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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>
|
|
281
|
-
</DropdownMenuContent>
|
|
282
|
-
</DropdownMenu>
|
|
283
|
-
</div>
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
// Figma: Have section (DropdownMenuLabel as section header)
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
export const WithSection = {
|
|
216
|
+
name: "Have Section",
|
|
217
|
+
render: () => (
|
|
218
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
219
|
+
<div>
|
|
220
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">With Section Header</p>
|
|
221
|
+
<DropdownMenu open>
|
|
222
|
+
<DropdownMenuTrigger asChild>
|
|
223
|
+
<ActionButton variant="icon">
|
|
224
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
225
|
+
</ActionButton>
|
|
226
|
+
</DropdownMenuTrigger>
|
|
227
|
+
<DropdownMenuContent className="relative" style={{ position: "static", transform: "none" }}>
|
|
228
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
229
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
230
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
231
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
232
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
233
|
+
<DropdownMenuSeparator />
|
|
234
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
235
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
236
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
237
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
238
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
239
|
+
</DropdownMenuContent>
|
|
240
|
+
</DropdownMenu>
|
|
284
241
|
</div>
|
|
285
|
-
);
|
|
286
|
-
},
|
|
287
|
-
} satisfies StoryObj;
|
|
288
242
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
<
|
|
305
|
-
|
|
306
|
-
</
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
310
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
311
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
312
|
-
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
313
|
-
</DropdownMenuContent>
|
|
314
|
-
</DropdownMenu>
|
|
315
|
-
</div>
|
|
243
|
+
<div>
|
|
244
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
245
|
+
<DropdownMenu>
|
|
246
|
+
<DropdownMenuTrigger asChild>
|
|
247
|
+
<Button variant="outline">Open Menu</Button>
|
|
248
|
+
</DropdownMenuTrigger>
|
|
249
|
+
<DropdownMenuContent>
|
|
250
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
251
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
252
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
253
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
254
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
255
|
+
<DropdownMenuSeparator />
|
|
256
|
+
<DropdownMenuLabel>Section Name</DropdownMenuLabel>
|
|
257
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
258
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
259
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
260
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
261
|
+
</DropdownMenuContent>
|
|
262
|
+
</DropdownMenu>
|
|
316
263
|
</div>
|
|
317
|
-
|
|
318
|
-
|
|
264
|
+
</div>
|
|
265
|
+
),
|
|
319
266
|
} satisfies StoryObj;
|
|
320
267
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
render: (
|
|
328
|
-
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Figma: Have search
|
|
270
|
+
// Dropdown with search input at the top
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
export const WithSearch = {
|
|
273
|
+
name: "Have Search",
|
|
274
|
+
render: () => {
|
|
275
|
+
const [query, setQuery] = useState("");
|
|
276
|
+
const allOptions = [
|
|
277
|
+
"Option Description",
|
|
278
|
+
"Project Alpha",
|
|
279
|
+
"Project Beta",
|
|
280
|
+
"Project Gamma",
|
|
281
|
+
"Project Delta",
|
|
282
|
+
"Project Epsilon",
|
|
283
|
+
"Project Zeta",
|
|
284
|
+
"Project Eta",
|
|
285
|
+
"Project Theta",
|
|
286
|
+
];
|
|
287
|
+
const filtered = allOptions.filter((o) =>
|
|
288
|
+
o.toLowerCase().includes(query.toLowerCase())
|
|
289
|
+
);
|
|
290
|
+
|
|
332
291
|
return (
|
|
333
|
-
<div className="flex
|
|
334
|
-
<div
|
|
335
|
-
<
|
|
292
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
293
|
+
<div>
|
|
294
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">With Search Field</p>
|
|
295
|
+
<DropdownMenu open>
|
|
336
296
|
<DropdownMenuTrigger asChild>
|
|
337
297
|
<ActionButton variant="icon">
|
|
338
298
|
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
339
299
|
</ActionButton>
|
|
340
300
|
</DropdownMenuTrigger>
|
|
341
|
-
<DropdownMenuContent
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
<
|
|
301
|
+
<DropdownMenuContent
|
|
302
|
+
className="relative w-[230px]"
|
|
303
|
+
style={{ position: "static", transform: "none" }}
|
|
304
|
+
onInteractOutside={(e: Event) => e.preventDefault()}
|
|
305
|
+
>
|
|
306
|
+
<div className="flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]">
|
|
307
|
+
<Icon type="heroicons" name="magnifying-glass" className="size-[14px] shrink-0 text-text-g-contrast-medium mr-1" />
|
|
308
|
+
<Input
|
|
309
|
+
variant="flat"
|
|
310
|
+
size="sm"
|
|
311
|
+
className="flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium"
|
|
312
|
+
placeholder="Search"
|
|
313
|
+
value={query}
|
|
314
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
315
|
+
/>
|
|
316
|
+
</div>
|
|
317
|
+
{filtered.map((label) => (
|
|
318
|
+
<DropdownMenuItem key={label}>{label}</DropdownMenuItem>
|
|
319
|
+
))}
|
|
320
|
+
{filtered.length === 0 && (
|
|
321
|
+
<div className="px-4 py-3 typography-subtitle4 text-text-g-contrast-medium">
|
|
322
|
+
No results found
|
|
323
|
+
</div>
|
|
324
|
+
)}
|
|
347
325
|
</DropdownMenuContent>
|
|
348
326
|
</DropdownMenu>
|
|
349
327
|
</div>
|
|
350
|
-
</div>
|
|
351
|
-
);
|
|
352
|
-
},
|
|
353
|
-
} satisfies StoryObj;
|
|
354
328
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
side: "bottom",
|
|
358
|
-
align: "center",
|
|
359
|
-
sideOffset: 5,
|
|
360
|
-
alignOffset: 0,
|
|
361
|
-
},
|
|
362
|
-
render: (args) => {
|
|
363
|
-
console.log("args ", args);
|
|
364
|
-
const props: typeof args = {
|
|
365
|
-
...args,
|
|
366
|
-
};
|
|
367
|
-
return (
|
|
368
|
-
<div className="flex flex-row gap-4 w-full">
|
|
369
|
-
<div className="flex flex-1 justify-center items-center space-x-2">
|
|
329
|
+
<div>
|
|
330
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
370
331
|
<DropdownMenu>
|
|
371
332
|
<DropdownMenuTrigger asChild>
|
|
372
|
-
<
|
|
373
|
-
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
374
|
-
</ActionButton>
|
|
333
|
+
<Button variant="outline">Open Menu</Button>
|
|
375
334
|
</DropdownMenuTrigger>
|
|
376
|
-
<DropdownMenuContent
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
335
|
+
<DropdownMenuContent className="w-[230px]">
|
|
336
|
+
<div className="flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]">
|
|
337
|
+
<Icon type="heroicons" name="magnifying-glass" className="size-[14px] shrink-0 text-text-g-contrast-medium mr-1" />
|
|
338
|
+
<Input
|
|
339
|
+
variant="flat"
|
|
340
|
+
size="sm"
|
|
341
|
+
className="flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium"
|
|
342
|
+
placeholder="Search"
|
|
343
|
+
/>
|
|
344
|
+
</div>
|
|
383
345
|
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
384
346
|
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
385
347
|
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
@@ -392,3 +354,226 @@ export const Position = {
|
|
|
392
354
|
);
|
|
393
355
|
},
|
|
394
356
|
} satisfies StoryObj;
|
|
357
|
+
|
|
358
|
+
// ---------------------------------------------------------------------------
|
|
359
|
+
// Figma: Can scroll — long list, overflow-y scrollable
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
export const CanScroll = {
|
|
362
|
+
name: "Can Scroll",
|
|
363
|
+
render: () => (
|
|
364
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
365
|
+
<div>
|
|
366
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Scrollable List</p>
|
|
367
|
+
<DropdownMenu open>
|
|
368
|
+
<DropdownMenuTrigger asChild>
|
|
369
|
+
<ActionButton variant="icon">
|
|
370
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
371
|
+
</ActionButton>
|
|
372
|
+
</DropdownMenuTrigger>
|
|
373
|
+
<DropdownMenuContent
|
|
374
|
+
className="relative max-h-[270px] overflow-y-auto"
|
|
375
|
+
style={{ position: "static", transform: "none" }}
|
|
376
|
+
>
|
|
377
|
+
{Array.from({ length: 10 }, (_, i) => (
|
|
378
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
379
|
+
))}
|
|
380
|
+
</DropdownMenuContent>
|
|
381
|
+
</DropdownMenu>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
<div>
|
|
385
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
386
|
+
<DropdownMenu>
|
|
387
|
+
<DropdownMenuTrigger asChild>
|
|
388
|
+
<Button variant="outline">Open Menu</Button>
|
|
389
|
+
</DropdownMenuTrigger>
|
|
390
|
+
<DropdownMenuContent className="max-h-[270px] overflow-y-auto">
|
|
391
|
+
{Array.from({ length: 10 }, (_, i) => (
|
|
392
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
393
|
+
))}
|
|
394
|
+
</DropdownMenuContent>
|
|
395
|
+
</DropdownMenu>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
),
|
|
399
|
+
} satisfies StoryObj;
|
|
400
|
+
|
|
401
|
+
// ---------------------------------------------------------------------------
|
|
402
|
+
// Figma: Double scroll — two separate scrollable sections with section headers
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
export const DoubleScroll = {
|
|
405
|
+
name: "Double Scroll",
|
|
406
|
+
render: () => (
|
|
407
|
+
<div className="flex gap-8 items-start flex-wrap">
|
|
408
|
+
<div>
|
|
409
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Two Scrollable Sections</p>
|
|
410
|
+
<DropdownMenu open>
|
|
411
|
+
<DropdownMenuTrigger asChild>
|
|
412
|
+
<ActionButton variant="icon">
|
|
413
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
414
|
+
</ActionButton>
|
|
415
|
+
</DropdownMenuTrigger>
|
|
416
|
+
<DropdownMenuContent
|
|
417
|
+
className="relative"
|
|
418
|
+
style={{ position: "static", transform: "none" }}
|
|
419
|
+
>
|
|
420
|
+
<DropdownMenuLabel>Section A</DropdownMenuLabel>
|
|
421
|
+
<div className="max-h-[270px] overflow-y-auto">
|
|
422
|
+
{Array.from({ length: 5 }, (_, i) => (
|
|
423
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
424
|
+
))}
|
|
425
|
+
</div>
|
|
426
|
+
<DropdownMenuSeparator />
|
|
427
|
+
<DropdownMenuLabel>Section B</DropdownMenuLabel>
|
|
428
|
+
<div className="max-h-[216px] overflow-y-auto">
|
|
429
|
+
{Array.from({ length: 4 }, (_, i) => (
|
|
430
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
431
|
+
))}
|
|
432
|
+
</div>
|
|
433
|
+
</DropdownMenuContent>
|
|
434
|
+
</DropdownMenu>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<div>
|
|
438
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Interactive</p>
|
|
439
|
+
<DropdownMenu>
|
|
440
|
+
<DropdownMenuTrigger asChild>
|
|
441
|
+
<Button variant="outline">Open Menu</Button>
|
|
442
|
+
</DropdownMenuTrigger>
|
|
443
|
+
<DropdownMenuContent>
|
|
444
|
+
<DropdownMenuLabel>Section A</DropdownMenuLabel>
|
|
445
|
+
<div className="max-h-[270px] overflow-y-auto">
|
|
446
|
+
{Array.from({ length: 5 }, (_, i) => (
|
|
447
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
448
|
+
))}
|
|
449
|
+
</div>
|
|
450
|
+
<DropdownMenuSeparator />
|
|
451
|
+
<DropdownMenuLabel>Section B</DropdownMenuLabel>
|
|
452
|
+
<div className="max-h-[216px] overflow-y-auto">
|
|
453
|
+
{Array.from({ length: 4 }, (_, i) => (
|
|
454
|
+
<DropdownMenuItem key={i}>Option Description {i + 1}</DropdownMenuItem>
|
|
455
|
+
))}
|
|
456
|
+
</div>
|
|
457
|
+
</DropdownMenuContent>
|
|
458
|
+
</DropdownMenu>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
),
|
|
462
|
+
} satisfies StoryObj;
|
|
463
|
+
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
// Figma: Sub menu (existing, preserved)
|
|
466
|
+
// ---------------------------------------------------------------------------
|
|
467
|
+
export const SubMenu = {
|
|
468
|
+
name: "Sub Menu",
|
|
469
|
+
render: () => (
|
|
470
|
+
<DropdownMenu>
|
|
471
|
+
<DropdownMenuTrigger asChild>
|
|
472
|
+
<Button variant="outline">Open Menu</Button>
|
|
473
|
+
</DropdownMenuTrigger>
|
|
474
|
+
<DropdownMenuContent>
|
|
475
|
+
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
|
476
|
+
<DropdownMenuSeparator />
|
|
477
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
478
|
+
<DropdownMenuItem>Billing</DropdownMenuItem>
|
|
479
|
+
<DropdownMenuItem>Team</DropdownMenuItem>
|
|
480
|
+
<DropdownMenuSeparator />
|
|
481
|
+
<DropdownMenuGroup>
|
|
482
|
+
<DropdownMenuSub>
|
|
483
|
+
<DropdownMenuSubTrigger>
|
|
484
|
+
<Icon type="heroicons" name="user-group" className="size-4 shrink-0" />
|
|
485
|
+
Invite users
|
|
486
|
+
</DropdownMenuSubTrigger>
|
|
487
|
+
<DropdownMenuPortal>
|
|
488
|
+
<DropdownMenuSubContent>
|
|
489
|
+
<DropdownMenuItem>Email</DropdownMenuItem>
|
|
490
|
+
<DropdownMenuItem>Message</DropdownMenuItem>
|
|
491
|
+
<DropdownMenuSeparator />
|
|
492
|
+
<DropdownMenuItem>More...</DropdownMenuItem>
|
|
493
|
+
</DropdownMenuSubContent>
|
|
494
|
+
</DropdownMenuPortal>
|
|
495
|
+
</DropdownMenuSub>
|
|
496
|
+
<DropdownMenuCheckboxItem>Panel</DropdownMenuCheckboxItem>
|
|
497
|
+
</DropdownMenuGroup>
|
|
498
|
+
</DropdownMenuContent>
|
|
499
|
+
</DropdownMenu>
|
|
500
|
+
),
|
|
501
|
+
} satisfies StoryObj;
|
|
502
|
+
|
|
503
|
+
// ---------------------------------------------------------------------------
|
|
504
|
+
// Trigger variants (on icon button, etc.)
|
|
505
|
+
// ---------------------------------------------------------------------------
|
|
506
|
+
export const TriggerVariants = {
|
|
507
|
+
name: "Trigger Variants",
|
|
508
|
+
render: () => (
|
|
509
|
+
<div className="flex gap-8 items-center flex-wrap">
|
|
510
|
+
<div>
|
|
511
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Text Trigger</p>
|
|
512
|
+
<DropdownMenu>
|
|
513
|
+
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
|
|
514
|
+
<DropdownMenuContent>
|
|
515
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
516
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
517
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
518
|
+
</DropdownMenuContent>
|
|
519
|
+
</DropdownMenu>
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
<div>
|
|
523
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Button Trigger</p>
|
|
524
|
+
<DropdownMenu>
|
|
525
|
+
<DropdownMenuTrigger asChild>
|
|
526
|
+
<Button variant="outline">Open Menu</Button>
|
|
527
|
+
</DropdownMenuTrigger>
|
|
528
|
+
<DropdownMenuContent>
|
|
529
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
530
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
531
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
532
|
+
</DropdownMenuContent>
|
|
533
|
+
</DropdownMenu>
|
|
534
|
+
</div>
|
|
535
|
+
|
|
536
|
+
<div>
|
|
537
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Icon Button Trigger</p>
|
|
538
|
+
<DropdownMenu>
|
|
539
|
+
<DropdownMenuTrigger asChild>
|
|
540
|
+
<ActionButton variant="icon">
|
|
541
|
+
<Icon type="heroicons" name="ellipsis-vertical" />
|
|
542
|
+
</ActionButton>
|
|
543
|
+
</DropdownMenuTrigger>
|
|
544
|
+
<DropdownMenuContent>
|
|
545
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
546
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
547
|
+
<DropdownMenuItem>Option Description</DropdownMenuItem>
|
|
548
|
+
</DropdownMenuContent>
|
|
549
|
+
</DropdownMenu>
|
|
550
|
+
</div>
|
|
551
|
+
|
|
552
|
+
<div>
|
|
553
|
+
<p className="typography-small4 text-text-g-contrast-medium mb-2">Horizontal dots</p>
|
|
554
|
+
<DropdownMenu>
|
|
555
|
+
<DropdownMenuTrigger asChild>
|
|
556
|
+
<ActionButton variant="icon">
|
|
557
|
+
<Icon type="heroicons" name="ellipsis-horizontal" />
|
|
558
|
+
</ActionButton>
|
|
559
|
+
</DropdownMenuTrigger>
|
|
560
|
+
<DropdownMenuContent>
|
|
561
|
+
<DropdownMenuItem>
|
|
562
|
+
<Icon type="heroicons" name="pencil" className="size-4 shrink-0" />
|
|
563
|
+
Edit
|
|
564
|
+
</DropdownMenuItem>
|
|
565
|
+
<DropdownMenuItem>
|
|
566
|
+
<Icon type="heroicons" name="document-duplicate" className="size-4 shrink-0" />
|
|
567
|
+
Duplicate
|
|
568
|
+
</DropdownMenuItem>
|
|
569
|
+
<DropdownMenuSeparator />
|
|
570
|
+
<DropdownMenuItem disabled>
|
|
571
|
+
<Icon type="heroicons" name="trash" className="size-4 shrink-0" />
|
|
572
|
+
Delete
|
|
573
|
+
</DropdownMenuItem>
|
|
574
|
+
</DropdownMenuContent>
|
|
575
|
+
</DropdownMenu>
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
),
|
|
579
|
+
} satisfies StoryObj;
|