@reliability-design/web 1.4.6 → 1.4.8

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 (148) hide show
  1. package/CHANGELOG.md +246 -49
  2. package/dist/components/rel-accordion/README.md +133 -132
  3. package/dist/components/rel-alert/README.md +145 -141
  4. package/dist/components/rel-autocomplete/README.md +172 -61
  5. package/dist/components/rel-avatar/README.md +118 -130
  6. package/dist/components/rel-badge/README.md +97 -93
  7. package/dist/components/rel-breadcrumb/README.md +96 -102
  8. package/dist/components/rel-button/README.md +190 -130
  9. package/dist/components/rel-calendar/README.md +109 -109
  10. package/dist/components/rel-card/README.md +75 -94
  11. package/dist/components/rel-cardmedia/README.md +100 -127
  12. package/dist/components/rel-carousel/README.md +186 -166
  13. package/dist/components/rel-checkbox/README.md +96 -75
  14. package/dist/components/rel-chip/README.md +138 -121
  15. package/dist/components/rel-container/README.md +107 -99
  16. package/dist/components/rel-date-picker/README.md +200 -289
  17. package/dist/components/rel-divider/README.md +88 -100
  18. package/dist/components/rel-drawer/README.md +187 -200
  19. package/dist/components/rel-kbd/README.md +141 -151
  20. package/dist/components/rel-layout/README.md +34 -0
  21. package/dist/components/rel-menu/README.md +180 -151
  22. package/dist/components/rel-menubar/README.md +218 -329
  23. package/dist/components/rel-otp/README.md +171 -440
  24. package/dist/components/rel-pagination/README.md +100 -424
  25. package/dist/components/rel-popover/README.md +203 -568
  26. package/dist/components/rel-progress/README.md +88 -110
  27. package/dist/components/rel-radio/README.md +131 -138
  28. package/dist/components/rel-range-picker/README.md +165 -0
  29. package/dist/components/rel-resizable/README.md +199 -140
  30. package/dist/components/rel-segmented-button/README.md +156 -141
  31. package/dist/components/rel-select/README.md +156 -93
  32. package/dist/components/rel-sheet/README.md +168 -224
  33. package/dist/components/rel-skeleton/README.md +104 -0
  34. package/dist/components/rel-slider/README.md +131 -135
  35. package/dist/components/rel-snackbar/README.md +168 -134
  36. package/dist/components/rel-stepper/README.md +162 -160
  37. package/dist/components/rel-switch/README.md +117 -102
  38. package/dist/components/rel-tab/README.md +173 -163
  39. package/dist/components/rel-textfield/README.md +176 -69
  40. package/dist/components/rel-time-picker/README.md +122 -157
  41. package/dist/components/rel-toast/README.md +165 -148
  42. package/dist/components/rel-tooltip/README.md +119 -111
  43. package/dist/components/rel-upload/README.md +220 -0
  44. package/dist/index.d.mts +1726 -447
  45. package/dist/index.d.ts +1726 -447
  46. package/dist/index.js +13715 -10870
  47. package/dist/index.js.map +1 -1
  48. package/dist/index.mjs +14018 -11163
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/styles/focus-ring.ts +84 -0
  51. package/dist/styles/vars.css +892 -866
  52. package/dist/{vars-XNMTSRVN.css → vars-DXX6QOAG.css} +892 -866
  53. package/package.json +3 -2
  54. package/dist/components/rel-accordion/rel-accordion.ts +0 -336
  55. package/dist/components/rel-alert/rel-alert.ts +0 -305
  56. package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -720
  57. package/dist/components/rel-avatar/rel-avatar.ts +0 -142
  58. package/dist/components/rel-badge/rel-badge.ts +0 -175
  59. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
  60. package/dist/components/rel-button/rel-button.ts +0 -560
  61. package/dist/components/rel-calendar/index.ts +0 -1
  62. package/dist/components/rel-calendar/rel-calendar.ts +0 -565
  63. package/dist/components/rel-card/rel-card.ts +0 -88
  64. package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
  65. package/dist/components/rel-carousel/index.ts +0 -1
  66. package/dist/components/rel-carousel/rel-carousel.ts +0 -723
  67. package/dist/components/rel-chart/README.md +0 -286
  68. package/dist/components/rel-chart/index.ts +0 -1
  69. package/dist/components/rel-chart/rel-chart.ts +0 -754
  70. package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
  71. package/dist/components/rel-chip/rel-chip.ts +0 -483
  72. package/dist/components/rel-container/rel-container.ts +0 -95
  73. package/dist/components/rel-date-picker/date-format.test.ts +0 -43
  74. package/dist/components/rel-date-picker/date-format.ts +0 -47
  75. package/dist/components/rel-date-picker/date-parse.test.ts +0 -116
  76. package/dist/components/rel-date-picker/date-parse.ts +0 -178
  77. package/dist/components/rel-date-picker/index.ts +0 -1
  78. package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1676
  79. package/dist/components/rel-divider/rel-divider.ts +0 -54
  80. package/dist/components/rel-drawer/index.ts +0 -1
  81. package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
  82. package/dist/components/rel-drawer/rel-drawer.ts +0 -607
  83. package/dist/components/rel-kbd/rel-kbd.ts +0 -188
  84. package/dist/components/rel-layout/rel-layout.ts +0 -49
  85. package/dist/components/rel-menu/rel-menu.ts +0 -541
  86. package/dist/components/rel-menubar/index.ts +0 -2
  87. package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
  88. package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
  89. package/dist/components/rel-menubar/rel-menubar.ts +0 -777
  90. package/dist/components/rel-nav-menu/README.md +0 -289
  91. package/dist/components/rel-nav-menu/index.ts +0 -3
  92. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
  93. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
  94. package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
  95. package/dist/components/rel-navbar/README.md +0 -126
  96. package/dist/components/rel-navbar/rel-navbar.ts +0 -105
  97. package/dist/components/rel-otp/index.ts +0 -1
  98. package/dist/components/rel-otp/rel-otp.ts +0 -527
  99. package/dist/components/rel-pagination/index.ts +0 -1
  100. package/dist/components/rel-pagination/rel-pagination.ts +0 -522
  101. package/dist/components/rel-popover/index.ts +0 -2
  102. package/dist/components/rel-popover/rel-popover-content.ts +0 -81
  103. package/dist/components/rel-popover/rel-popover.ts +0 -475
  104. package/dist/components/rel-progress/rel-progress.ts +0 -234
  105. package/dist/components/rel-radio/rel-radio.ts +0 -481
  106. package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1688
  107. package/dist/components/rel-resizable/index.ts +0 -3
  108. package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
  109. package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
  110. package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
  111. package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -217
  112. package/dist/components/rel-select/rel-select.ts +0 -1416
  113. package/dist/components/rel-sheet/rel-sheet.ts +0 -610
  114. package/dist/components/rel-sidebar/README.md +0 -209
  115. package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1191
  116. package/dist/components/rel-skeleton/rel-skeleton.ts +0 -143
  117. package/dist/components/rel-slider/rel-slider.ts +0 -673
  118. package/dist/components/rel-snackbar/rel-snackbar.ts +0 -329
  119. package/dist/components/rel-stepper/rel-stepper.ts +0 -567
  120. package/dist/components/rel-switch/rel-switch.ts +0 -199
  121. package/dist/components/rel-tab/rel-tab.ts +0 -264
  122. package/dist/components/rel-table/README.md +0 -178
  123. package/dist/components/rel-table/rel-table-body.ts +0 -22
  124. package/dist/components/rel-table/rel-table-caption.ts +0 -30
  125. package/dist/components/rel-table/rel-table-cell.ts +0 -43
  126. package/dist/components/rel-table/rel-table-footer.ts +0 -24
  127. package/dist/components/rel-table/rel-table-head.ts +0 -47
  128. package/dist/components/rel-table/rel-table-header.ts +0 -22
  129. package/dist/components/rel-table/rel-table-row.ts +0 -37
  130. package/dist/components/rel-table/rel-table.ts +0 -62
  131. package/dist/components/rel-textfield/rel-textfield.ts +0 -1054
  132. package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1482
  133. package/dist/components/rel-time-picker/time-parse.test.ts +0 -67
  134. package/dist/components/rel-time-picker/time-parse.ts +0 -85
  135. package/dist/components/rel-toast/rel-toast.ts +0 -206
  136. package/dist/components/rel-tooltip/rel-tooltip.ts +0 -193
  137. package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
  138. package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
  139. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
  140. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
  141. package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
  142. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
  143. package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
  144. package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
  145. package/dist/components/rel-topbar/rel-topbar.ts +0 -446
  146. package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
  147. package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
  148. package/dist/components/rel-upload/rel-upload.ts +0 -968
@@ -1,151 +1,180 @@
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-fonts-font-family` - Font family
96
- - `--rel-body-sm-regular-font-size` - Font size
97
- - `--rel-body-xl-regular-font-size` - Chevron font size
98
- - `--rel-fonts-weight-body-medium` - Active item font weight
99
- - `--rel-body-sm-regular-line-height` - Line height
100
-
101
- ### Spacing Tokens
102
- - `--rel-spacing-3xs` - Menu vertical padding
103
- - `--rel-spacing-xs` - Item padding, gaps
104
- - `--rel-spacing-sm` - Item horizontal padding
105
- - `--rel-spacing-2xs` - Checkbox gap, submenu offset
106
-
107
- ### Color Tokens
108
- - `--rel-bg-surface` - Menu and submenu background
109
- - `--rel-text-default` - Default text color
110
- - `--rel-text-disabled` - Disabled item text
111
- - `--rel-bg-surface-elevated` - Hover and active background
112
- - `--rel-border-default` - Active press background
113
- - `--rel-bg-info` - Focus outline
114
-
115
- ### Shadow Tokens
116
- - `--rel-shadows-shadow-300` - Menu and submenu drop shadow
117
-
118
- ### Border Tokens
119
- - `--rel-border-radius-md` - 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)
1
+ # rel-menu
2
+
3
+ `<rel-menu>` is the vertical action menu of the Reliability Design System (Figma "Menu", 6326:2931). It renders the rows you pass in `items` as a `role="menu"` list with hover, pressed, active, disabled and virtual-focus states, in one of six `type` modes: single-select rows (`default`, plus the `fixed` / `fit` width variants), checkbox rows, radio-style `select-option` rows, or `arrow` rows that open a submenu flyout. It renders into the light DOM (no shadow root). `<rel-menu-item>` is registered alongside it as a declarative placeholder. Use `<rel-menu>` inside a `<rel-popover>` or dropdown for context and overflow actions; for a horizontal application menu bar use `<rel-menubar>`, and for a form field that picks a value use `<rel-select>`.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Single-select rows (default) at the three row heights: 48 / 40 / 32 px -->
9
+ <rel-menu id="actions" size="large"></rel-menu>
10
+ <rel-menu size="medium"></rel-menu>
11
+ <rel-menu size="small"></rel-menu>
12
+
13
+ <!-- Multi-select rows with a checkbox control -->
14
+ <rel-menu id="view" type="checkbox"></rel-menu>
15
+
16
+ <!-- Single-select rows with a radio control -->
17
+ <rel-menu id="sort" type="select-option"></rel-menu>
18
+
19
+ <!-- Rows with submenu flyouts -->
20
+ <rel-menu id="file" type="arrow"></rel-menu>
21
+
22
+ <!-- Width modes: fixed 300px (override with --rel-menu-width) or shrink to content -->
23
+ <rel-menu type="fixed" style="--rel-menu-width: 240px"></rel-menu>
24
+ <rel-menu type="fit"></rel-menu>
25
+
26
+ <!-- rel-menu-item is a registered placeholder: it renders nothing and rel-menu does not read it yet -->
27
+ <rel-menu-item label="Rename" value="rename" icon="settings"></rel-menu-item>
28
+ <rel-menu-item label="Delete" value="delete" disabled></rel-menu-item>
29
+ ```
30
+
31
+ ```js
32
+ const actions = document.getElementById("actions");
33
+ actions.items = [
34
+ { label: "Edit" },
35
+ { label: "Copy", active: true },
36
+ { label: "Paste" },
37
+ { label: "Delete", disabled: true },
38
+ ];
39
+ actions.addEventListener("rel-select", (e) => {
40
+ e.detail.item.label; // the row that was activated (its copy has active: true)
41
+ });
42
+
43
+ const view = document.getElementById("view");
44
+ view.items = [
45
+ { label: "Show grid", checked: true },
46
+ { label: "Show rulers" },
47
+ ];
48
+ view.addEventListener("rel-check", (e) => {
49
+ e.detail.item.label;
50
+ e.detail.checked; // new state of that row
51
+ });
52
+
53
+ const file = document.getElementById("file");
54
+ file.items = [
55
+ { label: "New", submenu: [{ label: "File" }, { label: "Folder" }] },
56
+ { label: "Open", submenu: [{ label: "Recent…" }, { label: "Browse…" }] },
57
+ { label: "Quit" }, // no submenu → fires rel-select
58
+ ];
59
+ file.addEventListener("rel-submenu-select", (e) => {
60
+ e.detail.parent.label; // "New"
61
+ e.detail.sub.label; // "Folder"
62
+ });
63
+
64
+ // The array is copied on assignment — reassign to update
65
+ actions.items = [...actions.items, { label: "Duplicate" }];
66
+ ```
67
+
68
+ <!-- readme-gen:start -->
69
+
70
+ <!-- Generated from rel-menu.ts — do not edit; run readme-generate.mjs -->
71
+
72
+ ## Elements
73
+
74
+ | Element | Class | Source |
75
+ | --- | --- | --- |
76
+ | `<rel-menu>` | `RelMenu` | `rel-menu.ts` |
77
+ | `<rel-menu-item>` | `RelMenuItem` | `rel-menu.ts` |
78
+
79
+ ## API
80
+
81
+ ### `<rel-menu>`
82
+
83
+ #### Attributes / Properties
84
+
85
+ | Property | Attribute | Type | Default | Description |
86
+ | --- | --- | --- | --- | --- |
87
+ | `type` | `type` | `"list" \| "checkbox" \| "select-option" \| "arrow" \| "default" \| "fixed" \| "fit"` | `"list"` | Row shape (Figma ".Menu Item" Type). `list` (default) = plain rows; `checkbox` = toggling rows with a checkbox; `select-option` = single-select rows with a trailing check. `arrow` is a code-only extension with no Figma counterpart: rows whose `submenu` opens a flyout. Because it rides this axis, submenus cannot currently be combined with checkbox or select-option rows — see the README. DEPRECATED values, all still working: `default` is the old spelling of `list`; `fixed` / `fit` were width modes and now set `width` instead, leaving the row shape at `list`. |
88
+ | `width` | `width` | `"fixed" \| "fit"` | `undefined` | Sizing mode (Figma "Menu" Type). Both modes are `--rel-menu-width` (300px) wide — Figma's Fixed and Fit variants are both 300px — and the axis varies the HEIGHT: `fixed` pins the panel to `--rel-menu-height` (500px) and scrolls, `fit` hugs its rows. `fit` previously varied the width instead, which was the wrong dimension. This was also fused into `type`, where choosing a width silently forced plain rows and choosing a row shape silently forced the default width. Reflected. |
89
+ | `size` | `size` | `"large" \| "medium" \| "small"` | `"large"` | Row size (Figma ".Menu Item" Size, 6326:616): large = 48px rows with body-lg labels (Figma default), medium = 40px / body-md, small = 32px / body-sm. Added in 1.4.7; before that rows were a fixed 36px. Reflected. |
90
+ | `items` | `items` | `MenuItem[]` | `[]` | The rows to render, in order. Each entry is a `MenuItem` (`label`, optional `active`, `checked`, `disabled`, `submenu`, `open`). The array is copied on assignment, so mutate and reassign it to update the menu. |
91
+
92
+ ### Events
93
+
94
+ | Event | Detail | Bubbles / composed | Description |
95
+ | --- | --- | --- | --- |
96
+ | `rel-check` | `{ item: updated, checked: updated.checked }` | bubbles / composed | Fired when a `type="checkbox"` row is toggled. Detail: `{ item: MenuItem, checked: boolean }` — `item` is the updated row. |
97
+ | `rel-select` | `{ item: updated }` | bubbles / composed | Fired when a row is activated in `default`, `select-option`, `fixed` or `fit` mode (and for submenu-less rows in `arrow` mode). Detail: `{ item: MenuItem }` — the row, now `active`. |
98
+ | `rel-submenu-select` | `{ parent: this._items[parentIndex], sub: this._items[parentIndex]?.submenu?.[subIndex], }` | bubbles / composed | Fired when an entry inside a `type="arrow"` submenu is activated (the submenu closes). Detail: `{ parent: MenuItem, sub: MenuItem }`. |
99
+
100
+ ### Slots
101
+
102
+ | Slot | Description |
103
+ | --- | --- |
104
+ | — | This element has no slots. |
105
+
106
+ ### CSS Parts
107
+
108
+ | Part | Description |
109
+ | --- | --- |
110
+ | `panel` | A submenu flyout (`type="arrow"` only; light-DOM `[part="panel"]` attribute) |
111
+ | `list` | The `role="menu"` root list (a light-DOM `[part="list"]` attribute) |
112
+
113
+ ### `<rel-menu-item>`
114
+
115
+ #### Attributes / Properties
116
+
117
+ | Property | Attribute | Type | Default | Description |
118
+ | --- | --- | --- | --- | --- |
119
+ | `label` | `label` | `string` | `""` | Display text of the item. |
120
+ | `value` | `value` | `string` | `""` | Value that identifies the item (not used by `rel-menu` today). |
121
+ | `disabled` | `disabled` | `boolean` | `false` | Marks the item as non-interactive. |
122
+ | `icon` | `icon` | `string` | `""` | `rel-icon` name to render before the label (not used by `rel-menu` today). |
123
+
124
+ ### Events
125
+
126
+ | Event | Detail | Bubbles / composed | Description |
127
+ | --- | --- | --- | --- |
128
+ | — | — | — | This element emits no custom events. |
129
+
130
+ ### Slots
131
+
132
+ | Slot | Description |
133
+ | --- | --- |
134
+ | — | This element has no slots. |
135
+
136
+ ### CSS Parts
137
+
138
+ | Part | Description |
139
+ | --- | --- |
140
+ | — | None exposed. |
141
+
142
+ <!-- readme-gen:end -->
143
+
144
+ ## Accessibility
145
+
146
+ - The list (part `list`) is a `role="menu"` named "Menu" with `tabindex="0"`. DOM focus stays on this container; the row that has virtual focus is exposed through `aria-activedescendant` (every row has a stable id) and highlighted with a 2px `--rel-border-focus` outline inset 2px.
147
+ - Row roles follow `type`: `menuitem` for `default` / `arrow` / `fixed` / `fit`, `menuitemcheckbox` with `aria-checked` for `checkbox`, `menuitemradio` with `aria-checked` for `select-option`. Checkbox and select-option rows carry `aria-label` = the row label because their inner `<rel-checkbox>` / `<rel-radio>` control is rendered `inert` and `aria-hidden` (the row itself is the single click target).
148
+ - Disabled rows have `aria-disabled="true"`, render at 40% opacity with a `not-allowed` cursor and ignore clicks and Enter / Space.
149
+ - In `type="arrow"`, a row with a `submenu` has `aria-haspopup="menu"` and `aria-expanded`; the flyout (part `panel`) is a nested `role="menu"` of `menuitem` rows.
150
+ - The container shows a 2px `--rel-border-focus` outline (2px offset) on `:focus-visible`.
151
+ - No live-region announcements are made.
152
+
153
+ | Key (virtual focus in the main list) | Action |
154
+ | --- | --- |
155
+ | ArrowDown / ArrowUp | Move virtual focus to the next / previous row (stops at the ends, no wrap) |
156
+ | Home / End | First / last row |
157
+ | Enter / Space | Activate the row: fires `rel-select` or `rel-check`; on an `arrow` row with a submenu, opens (locks) that submenu and moves virtual focus to its first entry |
158
+ | ArrowRight | `arrow` type: open the focused row's submenu and focus its first entry |
159
+ | ArrowLeft / Escape | Close any open submenu (Escape's propagation is stopped only when a submenu was open, so an enclosing popover does not close in the same keystroke) |
160
+
161
+ | Key (virtual focus inside an open submenu) | Action |
162
+ | --- | --- |
163
+ | ArrowDown / ArrowUp | Next / previous submenu entry |
164
+ | Home / End | First / last submenu entry |
165
+ | Enter / Space | Activate the entry (fires `rel-submenu-select`, closes the submenu) |
166
+ | ArrowLeft / Escape | Close the submenu and return virtual focus to its parent row |
167
+
168
+ ## Notes / Edge Cases
169
+
170
+ - **Known limitation — submenus are mutually exclusive with checkbox and select-option rows.** Figma models row shape and width as two independent axes, which is why they are now two props (`type` and `width`). Submenus, however, are a code-only feature with no Figma counterpart, and they ride the `type` axis as `type="arrow"` — so a checkbox menu with submenus cannot currently be expressed. Tracked for 3.0, where `arrow` would become its own boolean the same way the width values just moved off `type`.
171
+ - `MenuItem` shape: `{ label: string; active?: boolean; checked?: boolean; disabled?: boolean; submenu?: MenuItem[]; open?: boolean }`. `active` marks the selected row (`default`, `fixed`, `fit`, `select-option`, submenu entries), `checked` the checkbox state, `submenu` / `open` the flyout rows and their initial visibility (`arrow` only).
172
+ - The menu keeps an internal copy of `items`; user interaction updates that copy, never your array. Read the current state from the event detail (`item`, `checked`, `parent` / `sub`) — the objects in `e.detail` are the updated copies. Reassign `items` to change the rows.
173
+ - Light DOM: `createRenderRoot()` returns the element, so the menu's CSS is injected as a `<style>` block and page styles can reach it. The parts are plain `part` attributes — target them with `rel-menu [part="list"]` / `rel-menu [part="panel"]`, not `::part()`.
174
+ - `size` is reflected as an attribute and the row rules key off `rel-menu[size="…"]`; submenu rows follow the same size.
175
+ - `type="arrow"`: hovering a row opens its submenu and leaving closes it, unless the row was clicked — a click locks the submenu open (click again to unlock). Keyboard opening also locks. A click outside the menu (detected through `composedPath`, so it works inside shadow roots) closes every submenu. Only one submenu is open at a time. Rows without a `submenu` in this mode behave like `default` rows and fire `rel-select`.
176
+ - `rel-select` in `select-option` mode sets `active` on the chosen row and clears it on the others; the radio control mirrors that state. `rel-check` toggles independently per row.
177
+ - The flyout is positioned `left: 100%` of its row with `z-index: 20` and stays inside the menu's box, so a menu placed at the right edge of a clipping container will have its flyout cut off; the menu itself deliberately does not use `overflow: hidden`.
178
+ - `--rel-menu-width` (default 300px) is read only when `type="fixed"`; other types have `min-width: 220px` (`fit` drops it and uses `max-content`). Submenus have `min-width: 200px`.
179
+ - `<rel-menu-item>` renders nothing and is not read by `<rel-menu>` today; it exists so markup can carry item metadata for future declarative support. Build menus from the `items` property.
180
+ - This module imports `rel-checkbox`, `rel-radio` and `rel-icon`, so those elements are registered whenever `rel-menu` is loaded.