@reliability-design/web 1.0.3 → 1.1.1

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.
Files changed (126) hide show
  1. package/dist/components/rel-accordion/README.md +132 -0
  2. package/dist/components/rel-accordion/rel-accordion.ts +47 -16
  3. package/dist/components/rel-alert/README.md +141 -0
  4. package/dist/components/rel-alert/rel-alert.ts +101 -20
  5. package/dist/components/rel-avatar/README.md +119 -0
  6. package/dist/components/rel-avatar/rel-avatar.ts +3 -2
  7. package/dist/components/rel-badge/README.md +86 -0
  8. package/dist/components/rel-badge/rel-badge.ts +11 -7
  9. package/dist/components/rel-breadcrumb/README.md +102 -0
  10. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +12 -6
  11. package/dist/components/rel-button/README.md +130 -0
  12. package/dist/components/rel-button/rel-button.ts +64 -8
  13. package/dist/components/rel-calendar/README.md +109 -0
  14. package/dist/components/rel-calendar/index.ts +1 -0
  15. package/dist/components/rel-calendar/rel-calendar.ts +467 -0
  16. package/dist/components/rel-card/README.md +94 -0
  17. package/dist/components/rel-card/rel-card.ts +12 -3
  18. package/dist/components/rel-cardmedia/README.md +127 -0
  19. package/dist/components/rel-cardmedia/rel-cardmedia.ts +14 -4
  20. package/dist/components/rel-carousel/README.md +166 -0
  21. package/dist/components/rel-carousel/index.ts +1 -0
  22. package/dist/components/rel-carousel/rel-carousel.ts +468 -0
  23. package/dist/components/rel-chart/README.md +286 -0
  24. package/dist/components/rel-chart/index.ts +1 -0
  25. package/dist/components/rel-chart/rel-chart.ts +736 -0
  26. package/dist/components/rel-checkbox/README.md +77 -0
  27. package/dist/components/rel-checkbox/rel-checkbox.ts +51 -12
  28. package/dist/components/rel-chip/README.md +114 -0
  29. package/dist/components/rel-chip/rel-chip.ts +83 -9
  30. package/dist/components/rel-container/README.md +99 -0
  31. package/dist/components/rel-date-picker/README.md +253 -0
  32. package/dist/components/rel-date-picker/index.ts +1 -0
  33. package/dist/components/rel-date-picker/rel-date-picker.ts +916 -0
  34. package/dist/components/rel-divider/README.md +100 -0
  35. package/dist/components/rel-divider/rel-divider.ts +9 -0
  36. package/dist/components/rel-drawer/README.md +200 -0
  37. package/dist/components/rel-drawer/index.ts +1 -0
  38. package/dist/components/rel-drawer/rel-drawer-footer.ts +29 -0
  39. package/dist/components/rel-drawer/rel-drawer.ts +612 -0
  40. package/dist/components/rel-kbd/README.md +151 -0
  41. package/dist/components/rel-kbd/rel-kbd.ts +118 -0
  42. package/dist/components/rel-layout/README.md +88 -0
  43. package/dist/components/rel-menu/README.md +151 -0
  44. package/dist/components/rel-menu/rel-menu.ts +64 -24
  45. package/dist/components/rel-menubar/README.md +329 -0
  46. package/dist/components/rel-menubar/index.ts +2 -0
  47. package/dist/components/rel-menubar/rel-menubar-menu.ts +16 -0
  48. package/dist/components/rel-menubar/rel-menubar.ts +605 -0
  49. package/dist/components/rel-nav-menu/README.md +289 -0
  50. package/dist/components/rel-nav-menu/index.ts +3 -0
  51. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +240 -0
  52. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +53 -0
  53. package/dist/components/rel-nav-menu/rel-nav-menu.ts +227 -0
  54. package/dist/components/rel-navbar/README.md +126 -0
  55. package/dist/components/rel-navbar/rel-navbar.ts +104 -0
  56. package/dist/components/rel-otp/README.md +440 -0
  57. package/dist/components/rel-otp/index.ts +1 -0
  58. package/dist/components/rel-otp/rel-otp.ts +504 -0
  59. package/dist/components/rel-pagination/README.md +410 -0
  60. package/dist/components/rel-pagination/index.ts +1 -0
  61. package/dist/components/rel-pagination/rel-pagination.ts +381 -0
  62. package/dist/components/rel-popover/README.md +568 -0
  63. package/dist/components/rel-popover/index.ts +2 -0
  64. package/dist/components/rel-popover/rel-popover-content.ts +55 -0
  65. package/dist/components/rel-popover/rel-popover.ts +330 -0
  66. package/dist/components/rel-progress/README.md +110 -0
  67. package/dist/components/rel-progress/rel-progress.ts +32 -5
  68. package/dist/components/rel-radio/README.md +120 -0
  69. package/dist/components/rel-radio/rel-radio.ts +31 -6
  70. package/dist/components/rel-resizable/README.md +140 -0
  71. package/dist/components/rel-resizable/index.ts +3 -0
  72. package/dist/components/rel-resizable/rel-resizable-group.ts +374 -0
  73. package/dist/components/rel-resizable/rel-resizable-handle.ts +145 -0
  74. package/dist/components/rel-resizable/rel-resizable-panel.ts +47 -0
  75. package/dist/components/rel-segmented-button/README.md +141 -0
  76. package/dist/components/rel-segmented-button/rel-segmented-button.ts +18 -13
  77. package/dist/components/rel-select/README.md +107 -0
  78. package/dist/components/rel-select/rel-select.ts +28 -14
  79. package/dist/components/rel-sheet/README.md +224 -0
  80. package/dist/components/rel-sheet/rel-sheet.ts +684 -0
  81. package/dist/components/rel-sidebar/README.md +209 -0
  82. package/dist/components/rel-sidebar/rel-sidebar.ts +1166 -0
  83. package/dist/components/rel-slider/README.md +135 -0
  84. package/dist/components/rel-slider/rel-slider.ts +44 -9
  85. package/dist/components/rel-snackbar/README.md +134 -0
  86. package/dist/components/rel-snackbar/rel-snackbar.ts +109 -14
  87. package/dist/components/rel-stepper/README.md +160 -0
  88. package/dist/components/rel-stepper/rel-stepper.ts +38 -27
  89. package/dist/components/rel-switch/README.md +102 -0
  90. package/dist/components/rel-switch/rel-switch.ts +34 -12
  91. package/dist/components/rel-tab/README.md +163 -0
  92. package/dist/components/rel-tab/rel-tab.ts +79 -23
  93. package/dist/components/rel-table/README.md +178 -0
  94. package/dist/components/rel-table/rel-table-body.ts +21 -0
  95. package/dist/components/rel-table/rel-table-caption.ts +27 -0
  96. package/dist/components/rel-table/rel-table-cell.ts +42 -0
  97. package/dist/components/rel-table/rel-table-footer.ts +23 -0
  98. package/dist/components/rel-table/rel-table-head.ts +45 -0
  99. package/dist/components/rel-table/rel-table-header.ts +21 -0
  100. package/dist/components/rel-table/rel-table-row.ts +36 -0
  101. package/dist/components/rel-table/rel-table.ts +53 -0
  102. package/dist/components/rel-textfield/README.md +90 -0
  103. package/dist/components/rel-textfield/rel-textfield.ts +55 -39
  104. package/dist/components/rel-toast/README.md +148 -0
  105. package/dist/components/rel-toast/rel-toast.ts +63 -24
  106. package/dist/components/rel-tooltip/README.md +103 -0
  107. package/dist/components/rel-tooltip/rel-tooltip.ts +123 -80
  108. package/dist/components/rel-topbar/rel-topbar-actions.ts +23 -0
  109. package/dist/components/rel-topbar/rel-topbar-brand.ts +46 -0
  110. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +33 -0
  111. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +28 -0
  112. package/dist/components/rel-topbar/rel-topbar-item.ts +315 -0
  113. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +23 -0
  114. package/dist/components/rel-topbar/rel-topbar-profile.ts +248 -0
  115. package/dist/components/rel-topbar/rel-topbar-utilities.ts +23 -0
  116. package/dist/components/rel-topbar/rel-topbar.ts +329 -0
  117. package/dist/index.d.mts +831 -7
  118. package/dist/index.d.ts +831 -7
  119. package/dist/index.js +9500 -1564
  120. package/dist/index.js.map +1 -1
  121. package/dist/index.mjs +9240 -1344
  122. package/dist/index.mjs.map +1 -1
  123. package/dist/styles/vars.css +187 -25
  124. package/dist/vars-TBB4BMSD.css +346 -0
  125. package/package.json +2 -1
  126. package/dist/vars-6ZIUPIU4.css +0 -184
@@ -0,0 +1,151 @@
1
+ # rel-kbd
2
+
3
+ A keyboard key/shortcut pill component for displaying keyboard shortcuts and key combinations in a visually consistent way.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Basic usage -->
9
+ <rel-kbd>K</rel-kbd>
10
+
11
+ <!-- Keyboard shortcut combination -->
12
+ <rel-kbd>Ctrl</rel-kbd> + <rel-kbd>K</rel-kbd>
13
+
14
+ <!-- With variants -->
15
+ <rel-kbd variant="muted">⌘</rel-kbd>
16
+ <rel-kbd variant="default">Shift</rel-kbd>
17
+
18
+ <!-- Different sizes -->
19
+ <rel-kbd size="sm">Esc</rel-kbd>
20
+ <rel-kbd size="md">Enter</rel-kbd>
21
+ <rel-kbd size="lg">Space</rel-kbd>
22
+
23
+ <!-- Pill shape -->
24
+ <rel-kbd pill>R</rel-kbd>
25
+
26
+ <!-- Inset (pressed) appearance -->
27
+ <rel-kbd inset>Tab</rel-kbd>
28
+ ```
29
+
30
+ ## API
31
+
32
+ ### Properties
33
+
34
+ | Property | Type | Default | Description |
35
+ |----------|------|---------|-------------|
36
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Controls the size of the kbd element |
37
+ | `variant` | `"default" \| "muted"` | `"default"` | Visual style variant |
38
+ | `pill` | `boolean` | `false` | When true, renders with full rounded corners |
39
+ | `inset` | `boolean` | `false` | When true, renders with pressed/inset appearance |
40
+
41
+ ### Slots
42
+
43
+ | Slot | Description |
44
+ |------|-------------|
45
+ | (default) | The keyboard key label or character |
46
+
47
+ ### CSS Custom Properties
48
+
49
+ The component uses design tokens from the Reliability Design System:
50
+
51
+ #### Colors
52
+ - `--rel-colors-gray-light` - Default background
53
+ - `--rel-colors-gray-background` - Muted and inset backgrounds
54
+ - `--rel-colors-gray-heading` - Default text color
55
+ - `--rel-colors-gray-placeholder` - Muted text color
56
+ - `--rel-colors-gray-border` - Default border
57
+ - `--rel-colors-gray-divider` - Muted border
58
+
59
+ #### Typography
60
+ - `--rel-fontFamilies-primary` - Font family (Poppins)
61
+ - `--rel-fontWeights-medium` - Font weight (500)
62
+ - `--rel-fontSizes-xs` - Small size font
63
+ - `--rel-fontSizes-sm` - Medium size font
64
+ - `--rel-fontSizes-md` - Large size font
65
+
66
+ #### Spacing
67
+ - `--rel-spacing-space-3xs` (2px)
68
+ - `--rel-spacing-space-2xs` (4px)
69
+ - `--rel-spacing-space-xs` (8px)
70
+ - `--rel-spacing-space-sm` (12px)
71
+ - `--rel-spacing-space-md` (16px)
72
+
73
+ #### Borders
74
+ - `--rel-borders-width-stroke-100` (1px)
75
+ - `--rel-borders-radius-border-radius-100` (2px)
76
+ - `--rel-borders-radius-border-radius-200` (8px)
77
+ - `--rel-borders-radius-border-radius-500` (1000px - pill shape)
78
+
79
+ ## Examples
80
+
81
+ ### Search Shortcut
82
+ ```html
83
+ <p>Press <rel-kbd>Ctrl</rel-kbd> + <rel-kbd>K</rel-kbd> to search</p>
84
+ ```
85
+
86
+ ### Mac Shortcut
87
+ ```html
88
+ <p>Press <rel-kbd variant="muted">⌘</rel-kbd> + <rel-kbd>Shift</rel-kbd> + <rel-kbd pill>R</rel-kbd> to reload</p>
89
+ ```
90
+
91
+ ### Multiple Sizes
92
+ ```html
93
+ <div style="display: flex; gap: 8px; align-items: center;">
94
+ <rel-kbd size="sm">S</rel-kbd>
95
+ <rel-kbd size="md">M</rel-kbd>
96
+ <rel-kbd size="lg">L</rel-kbd>
97
+ </div>
98
+ ```
99
+
100
+ ### Pressed State
101
+ ```html
102
+ <p>Hold <rel-kbd inset>Space</rel-kbd> to preview</p>
103
+ ```
104
+
105
+ ## Accessibility
106
+
107
+ - Uses semantic `<kbd>` HTML element for proper semantics
108
+ - `role="presentation"` is set to avoid redundant announcements
109
+ - Non-interactive by default (no tabindex)
110
+ - Text content is fully accessible to screen readers
111
+ - Inherits text color that maintains sufficient contrast ratios
112
+
113
+ ## Styling Notes
114
+
115
+ ### Default Appearance
116
+ - Subtle background with light border
117
+ - Small inset highlight shadow for raised appearance
118
+ - Monospaced font weight for technical look
119
+
120
+ ### Muted Variant
121
+ - Lower contrast for secondary shortcuts
122
+ - Softer colors and reduced shadow
123
+
124
+ ### Pill Modifier
125
+ - Fully rounded corners using border-radius-500 token
126
+ - Ideal for single character keys
127
+
128
+ ### Inset Modifier
129
+ - Inverted shadow for pressed/active appearance
130
+ - Slight vertical translation for depth effect
131
+ - Darker background to indicate pressed state
132
+
133
+ ## Dark Mode Support
134
+
135
+ The component automatically supports dark mode when design tokens are configured with dark mode variants, as it exclusively uses CSS custom properties.
136
+
137
+ ## Browser Support
138
+
139
+ Compatible with all modern browsers that support:
140
+ - Web Components
141
+ - CSS Custom Properties
142
+ - Shadow DOM
143
+
144
+ ## Framework Integration
145
+
146
+ Works seamlessly with:
147
+ - Vanilla JavaScript
148
+ - Angular
149
+ - React (via wrapper)
150
+ - Vue
151
+ - Any framework that supports Web Components
@@ -0,0 +1,118 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("rel-kbd")
5
+ export class RelKbd extends LitElement {
6
+ @property({ type: String, reflect: true })
7
+ size: "sm" | "md" | "lg" = "md";
8
+
9
+ @property({ type: String, reflect: true })
10
+ variant: "default" | "muted" = "default";
11
+
12
+ @property({ type: Boolean, reflect: true })
13
+ pill = false;
14
+
15
+ @property({ type: Boolean, reflect: true })
16
+ inset = false;
17
+
18
+ static styles = css`
19
+ :host {
20
+ display: inline-flex;
21
+ }
22
+
23
+ kbd {
24
+ display: inline-flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ font-family: var(--rel-fontFamilies-primary);
28
+ font-weight: var(--rel-fontWeights-medium);
29
+ white-space: nowrap;
30
+ user-select: none;
31
+ transition: all 0.15s ease;
32
+ line-height: 1;
33
+ vertical-align: middle;
34
+ }
35
+
36
+ /* Size variants */
37
+ .kbd-sm {
38
+ font-size: var(--rel-fontSizes-xs);
39
+ padding: var(--rel-spacing-space-3xs) var(--rel-spacing-space-xs);
40
+ min-width: 20px;
41
+ height: 20px;
42
+ border-radius: var(--rel-borders-radius-border-radius-100);
43
+ }
44
+
45
+ .kbd-md {
46
+ font-size: var(--rel-fontSizes-sm);
47
+ padding: var(--rel-spacing-space-2xs) var(--rel-spacing-space-sm);
48
+ min-width: 24px;
49
+ height: 24px;
50
+ border-radius: var(--rel-borders-radius-border-radius-100);
51
+ }
52
+
53
+ .kbd-lg {
54
+ font-size: var(--rel-fontSizes-md);
55
+ padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-md);
56
+ min-width: 32px;
57
+ height: 32px;
58
+ border-radius: var(--rel-borders-radius-border-radius-200);
59
+ }
60
+
61
+ /* Variant: default */
62
+ .kbd-default {
63
+ background: var(--rel-colors-gray-light);
64
+ color: var(--rel-colors-gray-heading);
65
+ border: var(--rel-borders-width-stroke-100) solid var(--rel-colors-gray-border);
66
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 0 0 rgba(255, 255, 255, 0.5) inset;
67
+ }
68
+
69
+ /* Variant: muted */
70
+ .kbd-muted {
71
+ background: var(--rel-surface-secondary, #fafafa);
72
+ color: var(--rel-colors-gray-placeholder);
73
+ border: var(--rel-borders-width-stroke-100) solid var(--rel-colors-gray-divider);
74
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.03);
75
+ }
76
+
77
+ /* Pill modifier */
78
+ :host([pill]) .kbd-sm {
79
+ border-radius: var(--rel-borders-radius-border-radius-500);
80
+ }
81
+
82
+ :host([pill]) .kbd-md {
83
+ border-radius: var(--rel-borders-radius-border-radius-500);
84
+ }
85
+
86
+ :host([pill]) .kbd-lg {
87
+ border-radius: var(--rel-borders-radius-border-radius-500);
88
+ }
89
+
90
+ /* Inset modifier - pressed appearance */
91
+ :host([inset]) kbd {
92
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset, 0 1px 0 0 rgba(0, 0, 0, 0.05);
93
+ transform: translateY(1px);
94
+ }
95
+
96
+ :host([inset]) .kbd-default {
97
+ background: var(--rel-surface-secondary, #fafafa);
98
+ border-color: var(--rel-colors-gray-divider);
99
+ }
100
+
101
+ :host([inset]) .kbd-muted {
102
+ background: var(--rel-colors-gray-divider);
103
+ border-color: var(--rel-colors-gray-border);
104
+ }
105
+ `;
106
+
107
+ private get classes() {
108
+ return ["kbd", `kbd-${this.size}`, `kbd-${this.variant}`].join(" ");
109
+ }
110
+
111
+ render() {
112
+ return html`
113
+ <kbd class="${this.classes}" role="presentation">
114
+ <slot></slot>
115
+ </kbd>
116
+ `;
117
+ }
118
+ }
@@ -0,0 +1,88 @@
1
+ # rel-layout
2
+
3
+ ## Overview
4
+ A responsive CSS Grid layout component with automatic breakpoint handling. Provides a configurable grid with customizable column count and gap, automatically adapting to smaller viewports when `responsive` is enabled.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Basic 4-column grid -->
9
+ <rel-layout>
10
+ <div>Item 1</div>
11
+ <div>Item 2</div>
12
+ <div>Item 3</div>
13
+ <div>Item 4</div>
14
+ <div>Item 5</div>
15
+ <div>Item 6</div>
16
+ </rel-layout>
17
+
18
+ <!-- Custom columns and gap -->
19
+ <rel-layout columns="3" gap="24px">
20
+ <div>Column 1</div>
21
+ <div>Column 2</div>
22
+ <div>Column 3</div>
23
+ </rel-layout>
24
+
25
+ <!-- Fixed layout (non-responsive) -->
26
+ <rel-layout columns="2" gap="16px" responsive="false">
27
+ <div>Always 2 columns</div>
28
+ <div>Even on mobile</div>
29
+ </rel-layout>
30
+
31
+ <!-- Large gap with 6 columns -->
32
+ <rel-layout columns="6" gap="2rem">
33
+ <div>Item 1</div>
34
+ <div>Item 2</div>
35
+ <div>Item 3</div>
36
+ <div>Item 4</div>
37
+ <div>Item 5</div>
38
+ <div>Item 6</div>
39
+ </rel-layout>
40
+ ```
41
+
42
+ ## API
43
+
44
+ ### Attributes/Properties
45
+ | Name | Type | Default | Description |
46
+ |------|------|---------|-------------|
47
+ | `columns` | `number` | `4` | Number of columns in the grid |
48
+ | `gap` | `string` | `"1rem"` | CSS gap value (supports any CSS length unit) |
49
+ | `responsive` (reflected) | `boolean` | `true` | Enable automatic responsive breakpoints |
50
+
51
+ ## Events
52
+ None.
53
+
54
+ ## Slots
55
+ | Slot | Description |
56
+ |------|-------------|
57
+ | (default) | Grid items (any HTML elements) |
58
+
59
+ ## CSS Parts
60
+ None exposed.
61
+
62
+ ## Tokens / CSS Variables
63
+
64
+ ### Semantic Tokens
65
+ - `--rel-fontFamilies-primary` - Font family
66
+
67
+ ## Accessibility
68
+ - Uses standard CSS Grid, which is accessible by default
69
+ - Ensure grid items contain proper semantic HTML
70
+
71
+ ### Keyboard Interactions
72
+ - Standard browser navigation through grid items
73
+
74
+ ### Focus Behavior
75
+ - No specific focus handling (relies on slotted content)
76
+
77
+ ## Notes / Edge Cases
78
+ - **Responsive breakpoints** (only when `responsive` is true):
79
+ - **≤1024px**: 3 columns
80
+ - **≤768px**: 2 columns
81
+ - **≤480px**: 1 column
82
+ - The `responsive` attribute is reflected, so CSS can target `:host([responsive])`
83
+ - Responsive styles use `!important` to override inline column count
84
+ - If `responsive` is set to `false`, the grid maintains the specified column count at all viewport sizes
85
+ - The grid is `display: grid` with `width: 100%`
86
+ - The `columns` and `gap` properties are applied as inline styles for maximum flexibility
87
+ - The component is `display: block` and `width: 100%`
88
+ - Grid items do not have any default styling—you must style them yourself
@@ -0,0 +1,151 @@
1
+ # rel-menu
2
+
3
+ ## Overview
4
+ A rich menu component supporting three modes: default (selectable items), checkbox (multi-select), and arrow (nested submenus). Features keyboard navigation, focus management, disabled items, active states, and automatic submenu positioning.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Default menu (single selection) -->
9
+ <rel-menu id="defaultMenu" type="default"></rel-menu>
10
+ <script>
11
+ const menu = document.getElementById('defaultMenu');
12
+ menu.items = [
13
+ { label: 'Edit', active: false },
14
+ { label: 'Copy', active: true },
15
+ { label: 'Paste', active: false },
16
+ { label: 'Delete', disabled: true }
17
+ ];
18
+ menu.addEventListener('item-selected', (e) => {
19
+ console.log('Selected:', e.detail.item.label);
20
+ });
21
+ </script>
22
+
23
+ <!-- Checkbox menu (multi-select) -->
24
+ <rel-menu id="checkMenu" type="checkbox"></rel-menu>
25
+ <script>
26
+ const checkMenu = document.getElementById('checkMenu');
27
+ checkMenu.items = [
28
+ { label: 'Show Grid', checked: true },
29
+ { label: 'Show Rulers', checked: false },
30
+ { label: 'Show Guides', checked: true }
31
+ ];
32
+ checkMenu.addEventListener('item-checked', (e) => {
33
+ console.log(e.detail.item.label, 'is', e.detail.checked ? 'checked' : 'unchecked');
34
+ });
35
+ </script>
36
+
37
+ <!-- Arrow menu (nested submenus) -->
38
+ <rel-menu id="arrowMenu" type="arrow"></rel-menu>
39
+ <script>
40
+ const arrowMenu = document.getElementById('arrowMenu');
41
+ arrowMenu.items = [
42
+ { label: 'File', submenu: [
43
+ { label: 'New' },
44
+ { label: 'Open' },
45
+ { label: 'Save', disabled: false }
46
+ ]},
47
+ { label: 'Edit', submenu: [
48
+ { label: 'Undo' },
49
+ { label: 'Redo' }
50
+ ]},
51
+ { label: 'Help' }
52
+ ];
53
+ arrowMenu.addEventListener('submenu-selected', (e) => {
54
+ console.log('Submenu item:', e.detail.sub.label, 'from', e.detail.parent.label);
55
+ });
56
+ </script>
57
+ ```
58
+
59
+ ## API
60
+
61
+ ### Attributes/Properties
62
+ | Name | Type | Default | Description |
63
+ |------|------|---------|-------------|
64
+ | `type` | `"default" \| "checkbox" \| "arrow"` | `"default"` | Menu behavior mode |
65
+ | `items` | `MenuItem[]` | `[]` | Array of menu items (see MenuItem interface below) |
66
+
67
+ ### MenuItem Interface
68
+ ```typescript
69
+ interface MenuItem {
70
+ label: string; // Display text
71
+ active?: boolean; // Highlighted/selected state (default/arrow modes)
72
+ checked?: boolean; // Checkbox state (checkbox mode)
73
+ disabled?: boolean; // Disables interaction
74
+ submenu?: MenuItem[]; // Nested menu items (arrow mode)
75
+ open?: boolean; // Submenu visibility state (arrow mode)
76
+ }
77
+ ```
78
+
79
+ ## Events
80
+ | Event | Detail | Description |
81
+ |-------|--------|-------------|
82
+ | `item-selected` | `{ item: MenuItem }` | Fired when an item is selected (default mode) |
83
+ | `item-checked` | `{ item: MenuItem, checked: boolean }` | Fired when a checkbox item is toggled (checkbox mode) |
84
+ | `submenu-selected` | `{ parent: MenuItem, sub: MenuItem }` | Fired when a submenu item is selected (arrow mode) |
85
+
86
+ ## Slots
87
+ Default slot not used.
88
+
89
+ ## CSS Parts
90
+ None exposed.
91
+
92
+ ## Tokens / CSS Variables
93
+
94
+ ### Semantic Tokens
95
+ - `--rel-fontFamilies-primary` - Font family
96
+ - `--rel-fontSizes-sm` - Font size
97
+ - `--rel-fontSizes-lg` - Chevron font size
98
+ - `--rel-fontWeights-medium` - Active item font weight
99
+ - `--rel-lineHeights-sm` - Line height
100
+
101
+ ### Spacing Tokens
102
+ - `--rel-spacing-space-3xs` - Menu vertical padding
103
+ - `--rel-spacing-space-xs` - Item padding, gaps
104
+ - `--rel-spacing-space-sm` - Item horizontal padding
105
+ - `--rel-spacing-space-2xs` - Checkbox gap, submenu offset
106
+
107
+ ### Color Tokens
108
+ - `--rel-colors-white` - Menu and submenu background
109
+ - `--rel-text-primary` - Default text color
110
+ - `--rel-text-disabled` - Disabled item text
111
+ - `--rel-surface-secondary` - Hover and active background
112
+ - `--rel-colors-gray-divider` - Active press background
113
+ - `--rel-colors-blue-primary` - Focus outline
114
+
115
+ ### Shadow Tokens
116
+ - `--rel-shadows-shadow-300` - Menu and submenu drop shadow
117
+
118
+ ### Border Tokens
119
+ - `--rel-borders-radius-border-radius-300` - Border radius
120
+
121
+ ## Accessibility
122
+ - Uses `role="menu"` on container and `role="menuitem"` on items
123
+ - Keyboard navigation with Arrow keys, Enter, Space, and Escape
124
+ - Focus visible states with blue outline on menu and items
125
+ - Disabled items have reduced color and are non-interactive
126
+ - Close submenu when clicking outside the menu
127
+
128
+ ### Keyboard Interactions
129
+ - `Arrow Down` - Move focus to next item
130
+ - `Arrow Up` - Move focus to previous item
131
+ - `Arrow Right` - Open focused submenu (arrow mode)
132
+ - `Arrow Left / Escape` - Close all submenus
133
+ - `Enter / Space` - Activate focused item
134
+ - `Tab` - Focus menu container
135
+
136
+ ### Focus Behavior
137
+ - Menu container receives focus on Tab
138
+ - Focused items show blue outline with -2px offset (inside boundary)
139
+ - Focus index tracked programmatically for keyboard navigation
140
+
141
+ ## Notes / Edge Cases
142
+ - **Default mode**: Clicking an item sets `active: true` on that item and `active: false` on all others
143
+ - **Checkbox mode**: Clicking toggles the `checked` state; also clicking the checkbox input itself triggers the same event
144
+ - **Arrow mode**: Submenus open on hover (`mouseenter`) and clicking toggles them; clicking a submenu item closes the submenu
145
+ - Submenus are positioned absolutely at `left: 100%` and `top: -<padding>` relative to parent item
146
+ - Clicking outside the menu (document-level listener) closes all open submenus
147
+ - Disabled items cannot be activated, checked, or expanded
148
+ - In arrow mode, only one submenu can be open at a time (opening one closes others)
149
+ - The menu has a minimum width of `220px`, submenus have `200px`
150
+ - Chevron (▸) appears only on items with `submenu` in arrow mode
151
+ - Native checkbox inputs are used in checkbox mode (16px × 16px)