@reliability-design/web 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/rel-accordion/rel-accordion.stories.ts +313 -0
- package/dist/components/rel-accordion/rel-accordion.ts +114 -0
- package/dist/components/rel-alert/rel-alert.stories.ts +412 -0
- package/dist/components/rel-alert/rel-alert.ts +194 -0
- package/dist/components/rel-avatar/rel-avatar.stories.ts +327 -0
- package/dist/components/rel-avatar/rel-avatar.ts +100 -0
- package/dist/components/rel-badge/rel-badge.stories.ts +350 -0
- package/dist/components/rel-badge/rel-badge.ts +70 -0
- package/dist/components/rel-breadcrumb/rel-breadcrumb.stories.ts +306 -0
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +97 -0
- package/dist/components/rel-button/rel-button.stories.ts +356 -0
- package/dist/components/rel-button/rel-button.ts +204 -0
- package/dist/components/rel-card/rel-card.stories.ts +299 -0
- package/dist/components/rel-card/rel-card.ts +33 -0
- package/dist/components/rel-cardmedia/rel-cardmedia.stories.ts +368 -0
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +80 -0
- package/dist/components/rel-checkbox/rel-checkbox.stories.ts +414 -0
- package/dist/components/rel-checkbox/rel-checkbox.ts +164 -0
- package/dist/components/rel-chip/rel-chip.stories.ts +552 -0
- package/dist/components/rel-chip/rel-chip.ts +261 -0
- package/dist/components/rel-container/rel-container.stories.ts +239 -0
- package/dist/components/rel-container/rel-container.ts +74 -0
- package/dist/components/rel-divider/rel-divider.stories.ts +229 -0
- package/dist/components/rel-divider/rel-divider.ts +44 -0
- package/dist/components/rel-layout/rel-layout.stories.ts +713 -0
- package/dist/components/rel-layout/rel-layout.ts +60 -0
- package/dist/components/rel-menu/rel-menu.stories.ts +910 -0
- package/dist/components/rel-menu/rel-menu.ts +319 -0
- package/dist/components/rel-progress/rel-progress.stories.ts +817 -0
- package/dist/components/rel-progress/rel-progress.ts +182 -0
- package/dist/components/rel-radio/rel-radio.stories.ts +1048 -0
- package/dist/components/rel-radio/rel-radio.ts +187 -0
- package/dist/components/rel-segmented-button/rel-segmented-button.stories.ts +1079 -0
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +150 -0
- package/dist/components/rel-select/rel-select.stories.ts +1201 -0
- package/dist/components/rel-select/rel-select.ts +261 -0
- package/dist/components/rel-slider/rel-slider.stories.ts +730 -0
- package/dist/components/rel-slider/rel-slider.ts +440 -0
- package/dist/components/rel-snackbar/rel-snackbar.stories.ts +808 -0
- package/dist/components/rel-snackbar/rel-snackbar.ts +212 -0
- package/dist/components/rel-stepper/rel-stepper.stories.ts +752 -0
- package/dist/components/rel-stepper/rel-stepper.ts +425 -0
- package/dist/components/rel-switch/rel-switch.stories.ts +441 -0
- package/dist/components/rel-switch/rel-switch.ts +161 -0
- package/dist/components/rel-tab/rel-tab.stories.ts +492 -0
- package/dist/components/rel-tab/rel-tab.ts +145 -0
- package/dist/components/rel-textfield/rel-textfield.stories.ts +710 -0
- package/dist/components/rel-textfield/rel-textfield.ts +224 -0
- package/dist/components/rel-toast/rel-toast.stories.ts +394 -0
- package/dist/components/rel-toast/rel-toast.ts +154 -0
- package/dist/components/rel-tooltip/rel-tooltip.stories.ts +364 -0
- package/dist/components/rel-tooltip/rel-tooltip.ts +80 -0
- package/dist/index.d.mts +372 -0
- package/dist/index.d.ts +372 -0
- package/dist/index.js +4593 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4544 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/vars.css +184 -0
- package/package.json +32 -0
|
@@ -0,0 +1,910 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import './rel-menu';
|
|
4
|
+
import type { MenuItem } from './rel-menu';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The Menu component provides a flexible dropdown menu system with multiple types.
|
|
8
|
+
* Built with Lit web components for framework-agnostic usage with full token support.
|
|
9
|
+
*
|
|
10
|
+
* ## Features
|
|
11
|
+
* - **3 Menu Types**: default, checkbox, arrow (with submenus)
|
|
12
|
+
* - **Keyboard Navigation**: Arrow keys, Enter, Escape support
|
|
13
|
+
* - **Submenu Support**: Nested menus for hierarchical navigation
|
|
14
|
+
* - **Interactive States**: Active, disabled, checked states
|
|
15
|
+
* - **Token-Based Styling**: Uses design system tokens
|
|
16
|
+
* - **Accessible**: ARIA roles and keyboard interactions
|
|
17
|
+
*/
|
|
18
|
+
const meta: Meta = {
|
|
19
|
+
title: 'Components/Menu',
|
|
20
|
+
tags: ['autodocs'],
|
|
21
|
+
component: 'rel-menu',
|
|
22
|
+
argTypes: {
|
|
23
|
+
type: {
|
|
24
|
+
control: { type: 'select' },
|
|
25
|
+
options: ['default', 'checkbox', 'arrow'],
|
|
26
|
+
description: 'Menu type',
|
|
27
|
+
table: {
|
|
28
|
+
defaultValue: { summary: 'default' },
|
|
29
|
+
type: { summary: 'string' },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
type Story = StoryObj;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Default menu with selectable items
|
|
40
|
+
*/
|
|
41
|
+
export const Default: Story = {
|
|
42
|
+
render: () => {
|
|
43
|
+
const items: MenuItem[] = [
|
|
44
|
+
{ label: 'Profile', active: false },
|
|
45
|
+
{ label: 'Settings', active: false },
|
|
46
|
+
{ label: 'Dashboard', active: true },
|
|
47
|
+
{ label: 'Logout', active: false },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const menu = document.createElement('rel-menu') as any;
|
|
51
|
+
menu.type = 'default';
|
|
52
|
+
menu.items = items;
|
|
53
|
+
|
|
54
|
+
menu.addEventListener('item-selected', (e: CustomEvent) => {
|
|
55
|
+
console.log('Item selected:', e.detail.item.label);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return menu;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Menu with checkboxes for multiple selections
|
|
64
|
+
*/
|
|
65
|
+
export const Checkbox: Story = {
|
|
66
|
+
render: () => {
|
|
67
|
+
const items: MenuItem[] = [
|
|
68
|
+
{ label: 'Show Grid', checked: true },
|
|
69
|
+
{ label: 'Show Rulers', checked: false },
|
|
70
|
+
{ label: 'Show Guides', checked: true },
|
|
71
|
+
{ label: 'Snap to Grid', checked: false },
|
|
72
|
+
{ label: 'Show Comments', checked: true, disabled: false },
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const menu = document.createElement('rel-menu') as any;
|
|
76
|
+
menu.type = 'checkbox';
|
|
77
|
+
menu.items = items;
|
|
78
|
+
|
|
79
|
+
menu.addEventListener('item-checked', (e: CustomEvent) => {
|
|
80
|
+
console.log('Item checked:', e.detail.item.label, e.detail.checked);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return menu;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Menu with arrow indicators and submenus
|
|
89
|
+
*/
|
|
90
|
+
export const Arrow: Story = {
|
|
91
|
+
render: () => {
|
|
92
|
+
const items: MenuItem[] = [
|
|
93
|
+
{ label: 'New File', active: false },
|
|
94
|
+
{
|
|
95
|
+
label: 'Open Recent',
|
|
96
|
+
active: false,
|
|
97
|
+
submenu: [
|
|
98
|
+
{ label: 'project-1.txt', active: false },
|
|
99
|
+
{ label: 'notes.md', active: false },
|
|
100
|
+
{ label: 'data.json', active: false },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{ label: 'Save', active: false },
|
|
104
|
+
{
|
|
105
|
+
label: 'Export',
|
|
106
|
+
active: false,
|
|
107
|
+
submenu: [
|
|
108
|
+
{ label: 'PDF', active: false },
|
|
109
|
+
{ label: 'PNG', active: false },
|
|
110
|
+
{ label: 'SVG', active: false },
|
|
111
|
+
{ label: 'HTML', active: false },
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
const menu = document.createElement('rel-menu') as any;
|
|
117
|
+
menu.type = 'arrow';
|
|
118
|
+
menu.items = items;
|
|
119
|
+
|
|
120
|
+
menu.addEventListener('submenu-selected', (e: CustomEvent) => {
|
|
121
|
+
console.log('Submenu selected:', e.detail.parent.label, '→', e.detail.sub.label);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return menu;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Menu with disabled items
|
|
130
|
+
*/
|
|
131
|
+
export const WithDisabled: Story = {
|
|
132
|
+
render: () => {
|
|
133
|
+
const items: MenuItem[] = [
|
|
134
|
+
{ label: 'Cut', active: false, disabled: true },
|
|
135
|
+
{ label: 'Copy', active: false },
|
|
136
|
+
{ label: 'Paste', active: false, disabled: true },
|
|
137
|
+
{ label: 'Delete', active: false },
|
|
138
|
+
{ label: 'Select All', active: false },
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
const menu = document.createElement('rel-menu') as any;
|
|
142
|
+
menu.type = 'default';
|
|
143
|
+
menu.items = items;
|
|
144
|
+
|
|
145
|
+
return menu;
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Checkbox menu with disabled options
|
|
151
|
+
*/
|
|
152
|
+
export const CheckboxWithDisabled: Story = {
|
|
153
|
+
render: () => {
|
|
154
|
+
const items: MenuItem[] = [
|
|
155
|
+
{ label: 'Notifications', checked: true },
|
|
156
|
+
{ label: 'Email Updates', checked: false, disabled: true },
|
|
157
|
+
{ label: 'SMS Alerts', checked: true },
|
|
158
|
+
{ label: 'Push Notifications', checked: false },
|
|
159
|
+
{ label: 'Desktop Alerts', checked: true, disabled: true },
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const menu = document.createElement('rel-menu') as any;
|
|
163
|
+
menu.type = 'checkbox';
|
|
164
|
+
menu.items = items;
|
|
165
|
+
|
|
166
|
+
return menu;
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Complex arrow menu with multiple levels
|
|
172
|
+
*/
|
|
173
|
+
export const ComplexArrow: Story = {
|
|
174
|
+
render: () => {
|
|
175
|
+
const items: MenuItem[] = [
|
|
176
|
+
{ label: 'Home', active: false },
|
|
177
|
+
{
|
|
178
|
+
label: 'Products',
|
|
179
|
+
active: false,
|
|
180
|
+
submenu: [
|
|
181
|
+
{ label: 'Electronics', active: false },
|
|
182
|
+
{ label: 'Clothing', active: false },
|
|
183
|
+
{ label: 'Books', active: false },
|
|
184
|
+
{ label: 'Toys', active: false },
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
label: 'Services',
|
|
189
|
+
active: false,
|
|
190
|
+
submenu: [
|
|
191
|
+
{ label: 'Consulting', active: false },
|
|
192
|
+
{ label: 'Support', active: false },
|
|
193
|
+
{ label: 'Training', active: false },
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
{ label: 'About', active: false },
|
|
197
|
+
{ label: 'Contact', active: false },
|
|
198
|
+
];
|
|
199
|
+
|
|
200
|
+
const menu = document.createElement('rel-menu') as any;
|
|
201
|
+
menu.type = 'arrow';
|
|
202
|
+
menu.items = items;
|
|
203
|
+
|
|
204
|
+
return menu;
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* File menu example
|
|
210
|
+
*/
|
|
211
|
+
export const FileMenu: Story = {
|
|
212
|
+
render: () => {
|
|
213
|
+
const items: MenuItem[] = [
|
|
214
|
+
{ label: 'New', active: false },
|
|
215
|
+
{ label: 'Open...', active: false },
|
|
216
|
+
{
|
|
217
|
+
label: 'Open Recent',
|
|
218
|
+
active: false,
|
|
219
|
+
submenu: [
|
|
220
|
+
{ label: 'Document 1.txt', active: false },
|
|
221
|
+
{ label: 'Presentation.pptx', active: false },
|
|
222
|
+
{ label: 'Spreadsheet.xlsx', active: false },
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
{ label: 'Save', active: false },
|
|
226
|
+
{ label: 'Save As...', active: false },
|
|
227
|
+
{
|
|
228
|
+
label: 'Export',
|
|
229
|
+
active: false,
|
|
230
|
+
submenu: [
|
|
231
|
+
{ label: 'PDF Document', active: false },
|
|
232
|
+
{ label: 'PNG Image', active: false },
|
|
233
|
+
{ label: 'SVG Vector', active: false },
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{ label: 'Print', active: false, disabled: true },
|
|
237
|
+
{ label: 'Close', active: false },
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
const menu = document.createElement('rel-menu') as any;
|
|
241
|
+
menu.type = 'arrow';
|
|
242
|
+
menu.items = items;
|
|
243
|
+
|
|
244
|
+
return menu;
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* View options menu (checkbox)
|
|
250
|
+
*/
|
|
251
|
+
export const ViewMenu: Story = {
|
|
252
|
+
render: () => {
|
|
253
|
+
const items: MenuItem[] = [
|
|
254
|
+
{ label: 'Show Toolbar', checked: true },
|
|
255
|
+
{ label: 'Show Sidebar', checked: true },
|
|
256
|
+
{ label: 'Show Status Bar', checked: false },
|
|
257
|
+
{ label: 'Show Minimap', checked: true },
|
|
258
|
+
{ label: 'Show Breadcrumbs', checked: false },
|
|
259
|
+
{ label: 'Show Line Numbers', checked: true },
|
|
260
|
+
{ label: 'Word Wrap', checked: false },
|
|
261
|
+
];
|
|
262
|
+
|
|
263
|
+
const menu = document.createElement('rel-menu') as any;
|
|
264
|
+
menu.type = 'checkbox';
|
|
265
|
+
menu.items = items;
|
|
266
|
+
|
|
267
|
+
return menu;
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* User account menu
|
|
273
|
+
*/
|
|
274
|
+
export const UserMenu: Story = {
|
|
275
|
+
render: () => {
|
|
276
|
+
const items: MenuItem[] = [
|
|
277
|
+
{ label: 'My Profile', active: false },
|
|
278
|
+
{ label: 'Account Settings', active: false },
|
|
279
|
+
{
|
|
280
|
+
label: 'Preferences',
|
|
281
|
+
active: false,
|
|
282
|
+
submenu: [
|
|
283
|
+
{ label: 'Theme', active: false },
|
|
284
|
+
{ label: 'Language', active: false },
|
|
285
|
+
{ label: 'Privacy', active: false },
|
|
286
|
+
],
|
|
287
|
+
},
|
|
288
|
+
{ label: 'Billing', active: false },
|
|
289
|
+
{ label: 'Help & Support', active: false },
|
|
290
|
+
{ label: 'Sign Out', active: false },
|
|
291
|
+
];
|
|
292
|
+
|
|
293
|
+
const menu = document.createElement('rel-menu') as any;
|
|
294
|
+
menu.type = 'arrow';
|
|
295
|
+
menu.items = items;
|
|
296
|
+
|
|
297
|
+
return menu;
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Keyboard navigation demo
|
|
303
|
+
*/
|
|
304
|
+
export const KeyboardNavigation: Story = {
|
|
305
|
+
render: () => html`
|
|
306
|
+
<div style="display: flex; flex-direction: column; gap: 16px;">
|
|
307
|
+
<div style="background: var(--rel-colors-blue-tertiary); color: white; padding: 16px; border-radius: 8px;">
|
|
308
|
+
<strong>Keyboard Controls:</strong>
|
|
309
|
+
<ul style="margin: 8px 0 0; padding-left: 20px; font-size: 14px;">
|
|
310
|
+
<li>↑/↓ Arrow Keys: Navigate menu items</li>
|
|
311
|
+
<li>→ Arrow Key: Open submenu (arrow type)</li>
|
|
312
|
+
<li>← Arrow Key / Escape: Close submenu</li>
|
|
313
|
+
<li>Enter / Space: Select item</li>
|
|
314
|
+
<li>Tab: Focus menu</li>
|
|
315
|
+
</ul>
|
|
316
|
+
</div>
|
|
317
|
+
${(() => {
|
|
318
|
+
const items: MenuItem[] = [
|
|
319
|
+
{ label: 'First Item', active: false },
|
|
320
|
+
{
|
|
321
|
+
label: 'With Submenu',
|
|
322
|
+
active: false,
|
|
323
|
+
submenu: [
|
|
324
|
+
{ label: 'Submenu Item 1', active: false },
|
|
325
|
+
{ label: 'Submenu Item 2', active: false },
|
|
326
|
+
],
|
|
327
|
+
},
|
|
328
|
+
{ label: 'Third Item', active: false },
|
|
329
|
+
{ label: 'Fourth Item', active: false },
|
|
330
|
+
];
|
|
331
|
+
|
|
332
|
+
const menu = document.createElement('rel-menu') as any;
|
|
333
|
+
menu.type = 'arrow';
|
|
334
|
+
menu.items = items;
|
|
335
|
+
return menu;
|
|
336
|
+
})()}
|
|
337
|
+
</div>
|
|
338
|
+
`,
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* All menu types showcase
|
|
343
|
+
*/
|
|
344
|
+
export const AllTypes: Story = {
|
|
345
|
+
render: () => html`
|
|
346
|
+
<div style="display: flex; gap: 24px; flex-wrap: wrap;">
|
|
347
|
+
<div style="display: flex; flex-direction: column; gap: 12px;">
|
|
348
|
+
<h4 style="margin: 0; color: var(--rel-colors-gray-heading); font-size: 14px;">Default Menu</h4>
|
|
349
|
+
${(() => {
|
|
350
|
+
const items: MenuItem[] = [
|
|
351
|
+
{ label: 'Option 1', active: false },
|
|
352
|
+
{ label: 'Option 2', active: true },
|
|
353
|
+
{ label: 'Option 3', active: false },
|
|
354
|
+
{ label: 'Option 4', active: false },
|
|
355
|
+
];
|
|
356
|
+
const menu = document.createElement('rel-menu') as any;
|
|
357
|
+
menu.type = 'default';
|
|
358
|
+
menu.items = items;
|
|
359
|
+
return menu;
|
|
360
|
+
})()}
|
|
361
|
+
</div>
|
|
362
|
+
|
|
363
|
+
<div style="display: flex; flex-direction: column; gap: 12px;">
|
|
364
|
+
<h4 style="margin: 0; color: var(--rel-colors-gray-heading); font-size: 14px;">Checkbox Menu</h4>
|
|
365
|
+
${(() => {
|
|
366
|
+
const items: MenuItem[] = [
|
|
367
|
+
{ label: 'Feature 1', checked: true },
|
|
368
|
+
{ label: 'Feature 2', checked: false },
|
|
369
|
+
{ label: 'Feature 3', checked: true },
|
|
370
|
+
{ label: 'Feature 4', checked: false },
|
|
371
|
+
];
|
|
372
|
+
const menu = document.createElement('rel-menu') as any;
|
|
373
|
+
menu.type = 'checkbox';
|
|
374
|
+
menu.items = items;
|
|
375
|
+
return menu;
|
|
376
|
+
})()}
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
<div style="display: flex; flex-direction: column; gap: 12px;">
|
|
380
|
+
<h4 style="margin: 0; color: var(--rel-colors-gray-heading); font-size: 14px;">Arrow Menu</h4>
|
|
381
|
+
${(() => {
|
|
382
|
+
const items: MenuItem[] = [
|
|
383
|
+
{ label: 'Main 1', active: false },
|
|
384
|
+
{
|
|
385
|
+
label: 'Main 2',
|
|
386
|
+
active: false,
|
|
387
|
+
submenu: [
|
|
388
|
+
{ label: 'Sub 1', active: false },
|
|
389
|
+
{ label: 'Sub 2', active: false },
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
{ label: 'Main 3', active: false },
|
|
393
|
+
];
|
|
394
|
+
const menu = document.createElement('rel-menu') as any;
|
|
395
|
+
menu.type = 'arrow';
|
|
396
|
+
menu.items = items;
|
|
397
|
+
return menu;
|
|
398
|
+
})()}
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
`,
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Context menu example
|
|
406
|
+
*/
|
|
407
|
+
export const ContextMenu: Story = {
|
|
408
|
+
render: () => html`
|
|
409
|
+
<div style="display: flex; flex-direction: column; gap: 16px;">
|
|
410
|
+
<div style="background: var(--rel-colors-gray-light); padding: 24px; border-radius: 8px; text-align: center; color: var(--rel-colors-gray-primary);">
|
|
411
|
+
<p style="margin: 0;"><strong>Right-click menu simulation</strong></p>
|
|
412
|
+
<p style="margin: 8px 0 0; font-size: 13px;">This represents a typical context menu</p>
|
|
413
|
+
</div>
|
|
414
|
+
${(() => {
|
|
415
|
+
const items: MenuItem[] = [
|
|
416
|
+
{ label: 'Cut', active: false },
|
|
417
|
+
{ label: 'Copy', active: false },
|
|
418
|
+
{ label: 'Paste', active: false, disabled: true },
|
|
419
|
+
{ label: 'Delete', active: false },
|
|
420
|
+
{
|
|
421
|
+
label: 'Share',
|
|
422
|
+
active: false,
|
|
423
|
+
submenu: [
|
|
424
|
+
{ label: 'Email', active: false },
|
|
425
|
+
{ label: 'Social Media', active: false },
|
|
426
|
+
{ label: 'Copy Link', active: false },
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
{ label: 'Properties', active: false },
|
|
430
|
+
];
|
|
431
|
+
|
|
432
|
+
const menu = document.createElement('rel-menu') as any;
|
|
433
|
+
menu.type = 'arrow';
|
|
434
|
+
menu.items = items;
|
|
435
|
+
return menu;
|
|
436
|
+
})()}
|
|
437
|
+
</div>
|
|
438
|
+
`,
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Simple default menu - demonstrates basic selection behavior
|
|
443
|
+
*/
|
|
444
|
+
export const SimpleDefault: Story = {
|
|
445
|
+
render: () => {
|
|
446
|
+
const items: MenuItem[] = [
|
|
447
|
+
{ label: 'Home', active: true },
|
|
448
|
+
{ label: 'About', active: false },
|
|
449
|
+
{ label: 'Services', active: false },
|
|
450
|
+
{ label: 'Contact', active: false },
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
const menu = document.createElement('rel-menu') as any;
|
|
454
|
+
menu.type = 'default';
|
|
455
|
+
menu.items = items;
|
|
456
|
+
|
|
457
|
+
menu.addEventListener('item-selected', (e: CustomEvent) => {
|
|
458
|
+
console.log('Selected:', e.detail.item.label);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
return menu;
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Default menu with all disabled items except one
|
|
467
|
+
*/
|
|
468
|
+
export const DefaultMostlyDisabled: Story = {
|
|
469
|
+
render: () => {
|
|
470
|
+
const items: MenuItem[] = [
|
|
471
|
+
{ label: 'New Project', active: false, disabled: true },
|
|
472
|
+
{ label: 'Open Project', active: false },
|
|
473
|
+
{ label: 'Save Project', active: false, disabled: true },
|
|
474
|
+
{ label: 'Close Project', active: false, disabled: true },
|
|
475
|
+
{ label: 'Exit', active: false, disabled: true },
|
|
476
|
+
];
|
|
477
|
+
|
|
478
|
+
const menu = document.createElement('rel-menu') as any;
|
|
479
|
+
menu.type = 'default';
|
|
480
|
+
menu.items = items;
|
|
481
|
+
|
|
482
|
+
return menu;
|
|
483
|
+
},
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Simple checkbox menu - demonstrates basic checkbox functionality
|
|
488
|
+
*/
|
|
489
|
+
export const SimpleCheckbox: Story = {
|
|
490
|
+
render: () => {
|
|
491
|
+
const items: MenuItem[] = [
|
|
492
|
+
{ label: 'Remember me', checked: true },
|
|
493
|
+
{ label: 'Stay signed in', checked: false },
|
|
494
|
+
{ label: 'Enable notifications', checked: false },
|
|
495
|
+
{ label: 'Auto-save', checked: true },
|
|
496
|
+
];
|
|
497
|
+
|
|
498
|
+
const menu = document.createElement('rel-menu') as any;
|
|
499
|
+
menu.type = 'checkbox';
|
|
500
|
+
menu.items = items;
|
|
501
|
+
|
|
502
|
+
menu.addEventListener('item-checked', (e: CustomEvent) => {
|
|
503
|
+
console.log('Checked:', e.detail.item.label, '=', e.detail.checked);
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
return menu;
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Checkbox menu with multiple checked items
|
|
512
|
+
*/
|
|
513
|
+
export const CheckboxMultipleChecked: Story = {
|
|
514
|
+
render: () => {
|
|
515
|
+
const items: MenuItem[] = [
|
|
516
|
+
{ label: 'JavaScript', checked: true },
|
|
517
|
+
{ label: 'TypeScript', checked: true },
|
|
518
|
+
{ label: 'Python', checked: true },
|
|
519
|
+
{ label: 'Java', checked: false },
|
|
520
|
+
{ label: 'C++', checked: false },
|
|
521
|
+
{ label: 'Ruby', checked: true },
|
|
522
|
+
{ label: 'Go', checked: true },
|
|
523
|
+
{ label: 'Rust', checked: false },
|
|
524
|
+
];
|
|
525
|
+
|
|
526
|
+
const menu = document.createElement('rel-menu') as any;
|
|
527
|
+
menu.type = 'checkbox';
|
|
528
|
+
menu.items = items;
|
|
529
|
+
|
|
530
|
+
return menu;
|
|
531
|
+
},
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Checkbox menu with mixed states and disabled
|
|
536
|
+
*/
|
|
537
|
+
export const CheckboxMixedStates: Story = {
|
|
538
|
+
render: () => {
|
|
539
|
+
const items: MenuItem[] = [
|
|
540
|
+
{ label: 'Dark Mode', checked: true },
|
|
541
|
+
{ label: 'High Contrast', checked: false, disabled: true },
|
|
542
|
+
{ label: 'Animations', checked: true },
|
|
543
|
+
{ label: 'Auto-play Videos', checked: false },
|
|
544
|
+
{ label: 'Reduced Motion', checked: false, disabled: true },
|
|
545
|
+
{ label: 'Large Text', checked: false },
|
|
546
|
+
{ label: 'Screen Reader', checked: true, disabled: true },
|
|
547
|
+
];
|
|
548
|
+
|
|
549
|
+
const menu = document.createElement('rel-menu') as any;
|
|
550
|
+
menu.type = 'checkbox';
|
|
551
|
+
menu.items = items;
|
|
552
|
+
|
|
553
|
+
return menu;
|
|
554
|
+
},
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Simple arrow menu - demonstrates basic submenu functionality
|
|
559
|
+
*/
|
|
560
|
+
export const SimpleArrow: Story = {
|
|
561
|
+
render: () => {
|
|
562
|
+
const items: MenuItem[] = [
|
|
563
|
+
{ label: 'Dashboard', active: false },
|
|
564
|
+
{
|
|
565
|
+
label: 'Reports',
|
|
566
|
+
active: false,
|
|
567
|
+
submenu: [
|
|
568
|
+
{ label: 'Monthly Report', active: false },
|
|
569
|
+
{ label: 'Quarterly Report', active: false },
|
|
570
|
+
{ label: 'Annual Report', active: false },
|
|
571
|
+
],
|
|
572
|
+
},
|
|
573
|
+
{ label: 'Settings', active: false },
|
|
574
|
+
];
|
|
575
|
+
|
|
576
|
+
const menu = document.createElement('rel-menu') as any;
|
|
577
|
+
menu.type = 'arrow';
|
|
578
|
+
menu.items = items;
|
|
579
|
+
|
|
580
|
+
menu.addEventListener('submenu-selected', (e: CustomEvent) => {
|
|
581
|
+
console.log('Selected:', e.detail.parent.label, '→', e.detail.sub.label);
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
return menu;
|
|
585
|
+
},
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Arrow menu with nested submenus and multiple items
|
|
590
|
+
*/
|
|
591
|
+
export const ArrowNestedComplex: Story = {
|
|
592
|
+
render: () => {
|
|
593
|
+
const items: MenuItem[] = [
|
|
594
|
+
{ label: 'File', active: false },
|
|
595
|
+
{
|
|
596
|
+
label: 'Edit',
|
|
597
|
+
active: false,
|
|
598
|
+
submenu: [
|
|
599
|
+
{ label: 'Undo', active: false },
|
|
600
|
+
{ label: 'Redo', active: false },
|
|
601
|
+
{ label: 'Cut', active: false },
|
|
602
|
+
{ label: 'Copy', active: false },
|
|
603
|
+
{ label: 'Paste', active: false },
|
|
604
|
+
{ label: 'Find', active: false },
|
|
605
|
+
{ label: 'Replace', active: false },
|
|
606
|
+
],
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
label: 'View',
|
|
610
|
+
active: false,
|
|
611
|
+
submenu: [
|
|
612
|
+
{ label: 'Zoom In', active: false },
|
|
613
|
+
{ label: 'Zoom Out', active: false },
|
|
614
|
+
{ label: 'Actual Size', active: false },
|
|
615
|
+
{ label: 'Fit to Window', active: false },
|
|
616
|
+
{ label: 'Full Screen', active: false },
|
|
617
|
+
],
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
label: 'Tools',
|
|
621
|
+
active: false,
|
|
622
|
+
submenu: [
|
|
623
|
+
{ label: 'Spell Check', active: false },
|
|
624
|
+
{ label: 'Word Count', active: false },
|
|
625
|
+
{ label: 'Character Map', active: false },
|
|
626
|
+
{ label: 'Color Picker', active: false },
|
|
627
|
+
],
|
|
628
|
+
},
|
|
629
|
+
{ label: 'Help', active: false },
|
|
630
|
+
];
|
|
631
|
+
|
|
632
|
+
const menu = document.createElement('rel-menu') as any;
|
|
633
|
+
menu.type = 'arrow';
|
|
634
|
+
menu.items = items;
|
|
635
|
+
|
|
636
|
+
return menu;
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Arrow menu with disabled parent and submenu items
|
|
642
|
+
*/
|
|
643
|
+
export const ArrowWithDisabled: Story = {
|
|
644
|
+
render: () => {
|
|
645
|
+
const items: MenuItem[] = [
|
|
646
|
+
{ label: 'New Document', active: false },
|
|
647
|
+
{
|
|
648
|
+
label: 'Import',
|
|
649
|
+
active: false,
|
|
650
|
+
disabled: true,
|
|
651
|
+
submenu: [
|
|
652
|
+
{ label: 'From File', active: false },
|
|
653
|
+
{ label: 'From URL', active: false },
|
|
654
|
+
{ label: 'From Clipboard', active: false },
|
|
655
|
+
],
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
label: 'Export',
|
|
659
|
+
active: false,
|
|
660
|
+
submenu: [
|
|
661
|
+
{ label: 'As PDF', active: false },
|
|
662
|
+
{ label: 'As Word', active: false, disabled: true },
|
|
663
|
+
{ label: 'As HTML', active: false },
|
|
664
|
+
{ label: 'As Text', active: false, disabled: true },
|
|
665
|
+
],
|
|
666
|
+
},
|
|
667
|
+
{ label: 'Print', active: false, disabled: true },
|
|
668
|
+
];
|
|
669
|
+
|
|
670
|
+
const menu = document.createElement('rel-menu') as any;
|
|
671
|
+
menu.type = 'arrow';
|
|
672
|
+
menu.items = items;
|
|
673
|
+
|
|
674
|
+
return menu;
|
|
675
|
+
},
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Navigation menu with hierarchical structure
|
|
680
|
+
*/
|
|
681
|
+
export const NavigationMenu: Story = {
|
|
682
|
+
render: () => {
|
|
683
|
+
const items: MenuItem[] = [
|
|
684
|
+
{ label: 'Home', active: true },
|
|
685
|
+
{
|
|
686
|
+
label: 'Products',
|
|
687
|
+
active: false,
|
|
688
|
+
submenu: [
|
|
689
|
+
{ label: 'All Products', active: false },
|
|
690
|
+
{ label: 'New Arrivals', active: false },
|
|
691
|
+
{ label: 'Best Sellers', active: false },
|
|
692
|
+
{ label: 'Sale Items', active: false },
|
|
693
|
+
{ label: 'Clearance', active: false },
|
|
694
|
+
],
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
label: 'Categories',
|
|
698
|
+
active: false,
|
|
699
|
+
submenu: [
|
|
700
|
+
{ label: 'Electronics', active: false },
|
|
701
|
+
{ label: 'Clothing', active: false },
|
|
702
|
+
{ label: 'Home & Garden', active: false },
|
|
703
|
+
{ label: 'Sports & Outdoors', active: false },
|
|
704
|
+
{ label: 'Toys & Games', active: false },
|
|
705
|
+
{ label: 'Books & Media', active: false },
|
|
706
|
+
],
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
label: 'Support',
|
|
710
|
+
active: false,
|
|
711
|
+
submenu: [
|
|
712
|
+
{ label: 'FAQs', active: false },
|
|
713
|
+
{ label: 'Contact Us', active: false },
|
|
714
|
+
{ label: 'Shipping Info', active: false },
|
|
715
|
+
{ label: 'Returns', active: false },
|
|
716
|
+
],
|
|
717
|
+
},
|
|
718
|
+
{ label: 'About Us', active: false },
|
|
719
|
+
];
|
|
720
|
+
|
|
721
|
+
const menu = document.createElement('rel-menu') as any;
|
|
722
|
+
menu.type = 'arrow';
|
|
723
|
+
menu.items = items;
|
|
724
|
+
|
|
725
|
+
return menu;
|
|
726
|
+
},
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Filter menu with checkboxes for search filters
|
|
731
|
+
*/
|
|
732
|
+
export const FilterMenu: Story = {
|
|
733
|
+
render: () => {
|
|
734
|
+
const items: MenuItem[] = [
|
|
735
|
+
{ label: 'In Stock', checked: true },
|
|
736
|
+
{ label: 'On Sale', checked: false },
|
|
737
|
+
{ label: 'Free Shipping', checked: true },
|
|
738
|
+
{ label: 'New Arrivals', checked: false },
|
|
739
|
+
{ label: 'Top Rated', checked: true },
|
|
740
|
+
{ label: 'Price: Low to High', checked: false },
|
|
741
|
+
{ label: 'Price: High to Low', checked: false },
|
|
742
|
+
{ label: 'Most Popular', checked: false },
|
|
743
|
+
];
|
|
744
|
+
|
|
745
|
+
const menu = document.createElement('rel-menu') as any;
|
|
746
|
+
menu.type = 'checkbox';
|
|
747
|
+
menu.items = items;
|
|
748
|
+
|
|
749
|
+
return menu;
|
|
750
|
+
},
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Settings menu with all checkbox options enabled
|
|
755
|
+
*/
|
|
756
|
+
export const SettingsAllEnabled: Story = {
|
|
757
|
+
render: () => {
|
|
758
|
+
const items: MenuItem[] = [
|
|
759
|
+
{ label: 'Auto-save', checked: true },
|
|
760
|
+
{ label: 'Cloud Sync', checked: true },
|
|
761
|
+
{ label: 'Offline Mode', checked: true },
|
|
762
|
+
{ label: 'Dark Theme', checked: true },
|
|
763
|
+
{ label: 'Notifications', checked: true },
|
|
764
|
+
{ label: 'Sound Effects', checked: true },
|
|
765
|
+
{ label: 'Haptic Feedback', checked: true },
|
|
766
|
+
];
|
|
767
|
+
|
|
768
|
+
const menu = document.createElement('rel-menu') as any;
|
|
769
|
+
menu.type = 'checkbox';
|
|
770
|
+
menu.items = items;
|
|
771
|
+
|
|
772
|
+
return menu;
|
|
773
|
+
},
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Editor context menu with realistic options
|
|
778
|
+
*/
|
|
779
|
+
export const EditorContextMenu: Story = {
|
|
780
|
+
render: () => {
|
|
781
|
+
const items: MenuItem[] = [
|
|
782
|
+
{ label: 'Undo', active: false },
|
|
783
|
+
{ label: 'Redo', active: false, disabled: true },
|
|
784
|
+
{ label: 'Cut', active: false },
|
|
785
|
+
{ label: 'Copy', active: false },
|
|
786
|
+
{ label: 'Paste', active: false },
|
|
787
|
+
{
|
|
788
|
+
label: 'Insert',
|
|
789
|
+
active: false,
|
|
790
|
+
submenu: [
|
|
791
|
+
{ label: 'Image', active: false },
|
|
792
|
+
{ label: 'Table', active: false },
|
|
793
|
+
{ label: 'Link', active: false },
|
|
794
|
+
{ label: 'Code Block', active: false },
|
|
795
|
+
{ label: 'Quote', active: false },
|
|
796
|
+
{ label: 'Divider', active: false },
|
|
797
|
+
],
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
label: 'Format',
|
|
801
|
+
active: false,
|
|
802
|
+
submenu: [
|
|
803
|
+
{ label: 'Bold', active: false },
|
|
804
|
+
{ label: 'Italic', active: false },
|
|
805
|
+
{ label: 'Underline', active: false },
|
|
806
|
+
{ label: 'Strikethrough', active: false },
|
|
807
|
+
{ label: 'Code', active: false },
|
|
808
|
+
],
|
|
809
|
+
},
|
|
810
|
+
{ label: 'Select All', active: false },
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
const menu = document.createElement('rel-menu') as any;
|
|
814
|
+
menu.type = 'arrow';
|
|
815
|
+
menu.items = items;
|
|
816
|
+
|
|
817
|
+
return menu;
|
|
818
|
+
},
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Application menu with extensive submenus
|
|
823
|
+
*/
|
|
824
|
+
export const ApplicationMenu: Story = {
|
|
825
|
+
render: () => {
|
|
826
|
+
const items: MenuItem[] = [
|
|
827
|
+
{ label: 'About Application', active: false },
|
|
828
|
+
{
|
|
829
|
+
label: 'Preferences',
|
|
830
|
+
active: false,
|
|
831
|
+
submenu: [
|
|
832
|
+
{ label: 'General', active: false },
|
|
833
|
+
{ label: 'Appearance', active: false },
|
|
834
|
+
{ label: 'Editor', active: false },
|
|
835
|
+
{ label: 'Extensions', active: false },
|
|
836
|
+
{ label: 'Keyboard Shortcuts', active: false },
|
|
837
|
+
{ label: 'Advanced', active: false },
|
|
838
|
+
],
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
label: 'Services',
|
|
842
|
+
active: false,
|
|
843
|
+
disabled: true,
|
|
844
|
+
submenu: [
|
|
845
|
+
{ label: 'Text to Speech', active: false },
|
|
846
|
+
{ label: 'Search', active: false },
|
|
847
|
+
{ label: 'New Email', active: false },
|
|
848
|
+
],
|
|
849
|
+
},
|
|
850
|
+
{ label: 'Hide Application', active: false },
|
|
851
|
+
{ label: 'Hide Others', active: false },
|
|
852
|
+
{ label: 'Show All', active: false },
|
|
853
|
+
{ label: 'Quit Application', active: false },
|
|
854
|
+
];
|
|
855
|
+
|
|
856
|
+
const menu = document.createElement('rel-menu') as any;
|
|
857
|
+
menu.type = 'arrow';
|
|
858
|
+
menu.items = items;
|
|
859
|
+
|
|
860
|
+
return menu;
|
|
861
|
+
},
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Developer tools menu
|
|
866
|
+
*/
|
|
867
|
+
export const DeveloperToolsMenu: Story = {
|
|
868
|
+
render: () => {
|
|
869
|
+
const items: MenuItem[] = [
|
|
870
|
+
{ label: 'Inspect Element', active: false },
|
|
871
|
+
{ label: 'View Source', active: false },
|
|
872
|
+
{
|
|
873
|
+
label: 'Console',
|
|
874
|
+
active: false,
|
|
875
|
+
submenu: [
|
|
876
|
+
{ label: 'Clear Console', active: false },
|
|
877
|
+
{ label: 'Preserve Log', active: false },
|
|
878
|
+
{ label: 'Show Timestamps', active: false },
|
|
879
|
+
],
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
label: 'Network',
|
|
883
|
+
active: false,
|
|
884
|
+
submenu: [
|
|
885
|
+
{ label: 'Clear Network Log', active: false },
|
|
886
|
+
{ label: 'Disable Cache', active: false },
|
|
887
|
+
{ label: 'Offline Mode', active: false },
|
|
888
|
+
{ label: 'Throttling', active: false },
|
|
889
|
+
],
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
label: 'Performance',
|
|
893
|
+
active: false,
|
|
894
|
+
submenu: [
|
|
895
|
+
{ label: 'Start Recording', active: false },
|
|
896
|
+
{ label: 'Take Heap Snapshot', active: false },
|
|
897
|
+
{ label: 'Collect Garbage', active: false },
|
|
898
|
+
],
|
|
899
|
+
},
|
|
900
|
+
{ label: 'Lighthouse', active: false },
|
|
901
|
+
{ label: 'Security', active: false },
|
|
902
|
+
];
|
|
903
|
+
|
|
904
|
+
const menu = document.createElement('rel-menu') as any;
|
|
905
|
+
menu.type = 'arrow';
|
|
906
|
+
menu.items = items;
|
|
907
|
+
|
|
908
|
+
return menu;
|
|
909
|
+
},
|
|
910
|
+
};
|