@reliability-design/web 1.4.9 → 1.4.10

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 (54) hide show
  1. package/CHANGELOG.md +155 -2
  2. package/custom-elements.json +18600 -0
  3. package/dist/components/rel-accordion/README.md +9 -2
  4. package/dist/components/rel-alert/README.md +4 -7
  5. package/dist/components/rel-autocomplete/README.md +209 -209
  6. package/dist/components/rel-avatar/README.md +228 -118
  7. package/dist/components/rel-breadcrumb/README.md +1 -0
  8. package/dist/components/rel-button/README.md +9 -9
  9. package/dist/components/rel-calendar/README.md +111 -109
  10. package/dist/components/rel-cardmedia/README.md +1 -1
  11. package/dist/components/rel-carousel/README.md +187 -187
  12. package/dist/components/rel-checkbox/README.md +159 -147
  13. package/dist/components/rel-chip/README.md +141 -138
  14. package/dist/components/rel-container/README.md +1 -1
  15. package/dist/components/rel-date-picker/README.md +221 -206
  16. package/dist/components/rel-drawer/README.md +4 -4
  17. package/dist/components/rel-kbd/README.md +188 -141
  18. package/dist/components/rel-layout/README.md +34 -34
  19. package/dist/components/rel-menu/README.md +17 -10
  20. package/dist/components/rel-menubar/README.md +218 -218
  21. package/dist/components/rel-otp/README.md +4 -8
  22. package/dist/components/rel-pagination/README.md +141 -100
  23. package/dist/components/rel-popover/README.md +220 -203
  24. package/dist/components/rel-radio/README.md +142 -131
  25. package/dist/components/rel-range-picker/README.md +194 -171
  26. package/dist/components/rel-resizable/README.md +220 -199
  27. package/dist/components/rel-segmented-button/README.md +158 -157
  28. package/dist/components/rel-select/README.md +20 -17
  29. package/dist/components/rel-sheet/README.md +3 -2
  30. package/dist/components/rel-signature-pad/README.md +161 -0
  31. package/dist/components/rel-slider/README.md +140 -131
  32. package/dist/components/rel-snackbar/README.md +170 -168
  33. package/dist/components/rel-split-button/README.md +129 -0
  34. package/dist/components/rel-stepper/README.md +171 -171
  35. package/dist/components/rel-switch/README.md +122 -117
  36. package/dist/components/rel-tab/README.md +184 -174
  37. package/dist/components/rel-textfield/README.md +21 -28
  38. package/dist/components/rel-time-picker/README.md +188 -170
  39. package/dist/components/rel-toast/README.md +20 -11
  40. package/dist/components/rel-tooltip/README.md +5 -4
  41. package/dist/components/rel-tree/README.md +157 -0
  42. package/dist/components/rel-upload/README.md +8 -5
  43. package/dist/index.d.mts +1602 -624
  44. package/dist/index.d.ts +1602 -624
  45. package/dist/index.js +11755 -6673
  46. package/dist/index.js.map +1 -1
  47. package/dist/index.mjs +10955 -5880
  48. package/dist/index.mjs.map +1 -1
  49. package/dist/styles/motion.css +31 -0
  50. package/dist/styles/motion.tokens.json +38 -0
  51. package/dist/styles/vars.css +88 -64
  52. package/dist/{vars-DXX6QOAG.css → vars-E22LYFMV.css} +88 -64
  53. package/package.json +60 -37
  54. package/dist/styles/focus-ring.ts +0 -84
@@ -1,141 +1,188 @@
1
- # rel-kbd
2
-
3
- `<rel-kbd>` is the single key cap from the Figma "Kbd" component (node 6316:284): a flat, bordered chip that shows a keyboard key or shortcut inline with text, in three heights (20 / 24 / 28px) and two fills (`default`, `muted`), with an `inset` pressed look. `<rel-kbd-group>` (Figma Kbd Items=1–4) renders a multi-key shortcut from an `items` array, one `<rel-kbd>` per key joined by "+" separators. Use them in help text, tooltips, menus and command palettes to display shortcuts. They are display-only — do not use them as buttons, and use `rel-chip` for tags or `rel-badge` for counts.
4
-
5
- ## Usage
6
-
7
- ```html
8
- <!-- Single key -->
9
- <rel-kbd>K</rel-kbd>
10
-
11
- <!-- Sizes -->
12
- <rel-kbd size="small">Esc</rel-kbd>
13
- <rel-kbd size="medium">Enter</rel-kbd>
14
- <rel-kbd size="large">Space</rel-kbd>
15
-
16
- <!-- Variants -->
17
- <rel-kbd variant="default">Shift</rel-kbd>
18
- <rel-kbd variant="muted">⌘</rel-kbd>
19
-
20
- <!-- Pressed look -->
21
- <p>Hold <rel-kbd inset>Space</rel-kbd> to preview</p>
22
-
23
- <!-- Multi-key shortcut from an items array (JSON attribute or property) -->
24
- <rel-kbd-group items='["Ctrl","Shift","P"]' size="medium"></rel-kbd-group>
25
- <rel-kbd-group id="palette" variant="muted" size="small"></rel-kbd-group>
26
- <script>
27
- document.getElementById("palette").items = ["⌘", "K"];
28
- </script>
29
-
30
- <!-- Inline with text -->
31
- <p>Press <rel-kbd-group items='["Ctrl","K"]'></rel-kbd-group> to search</p>
32
- ```
33
-
34
- ### Deprecated aliases
35
-
36
- ```html
37
- <!-- sm / md / lg → small / medium / large (accepted silently; no console notice) -->
38
- <rel-kbd size="sm">S</rel-kbd>
39
- <rel-kbd size="md">M</rel-kbd>
40
- <rel-kbd size="lg">L</rel-kbd>
41
- <rel-kbd-group items='["Ctrl","C"]' size="md"></rel-kbd-group>
42
-
43
- <!-- `pill` is deprecated → use the default 4px radius. Still renders fully rounded corners and logs once:
44
- [rel-kbd] "pill" is deprecated and will be removed in 3.0 — use "the default radius (4px at every size)" instead. The Kbd spec has one radius at every size; pill keeps working but is not part of the design. -->
45
- <rel-kbd pill>R</rel-kbd>
46
- ```
47
-
48
- <!-- readme-gen:start -->
49
-
50
- <!-- Generated from rel-kbd.ts — do not edit; run readme-generate.mjs -->
51
-
52
- ## Elements
53
-
54
- | Element | Class | Source |
55
- | --- | --- | --- |
56
- | `<rel-kbd>` | `RelKbd` | `rel-kbd.ts` |
57
- | `<rel-kbd-group>` | `RelKbdGroup` | `rel-kbd.ts` |
58
-
59
- ## API
60
-
61
- ### `<rel-kbd>`
62
-
63
- #### Attributes / Properties
64
-
65
- | Property | Attribute | Type | Default | Description |
66
- | --- | --- | --- | --- | --- |
67
- | `size` | `size` | `"sm" \| "md" \| "lg" \| "small" \| "medium" \| "large"` | `"md"` | Key-cap scale (Figma Size): `small` 20px tall / label-sm, `medium` 24px / label-md, `large` 28px / label-lg; 4px radius at every size. `sm` / `md` / `lg` are the legacy short spellings and stay accepted. Reflected. |
68
- | `variant` | `variant` | `"default" \| "muted"` | `"default"` | Fill / text contrast: `default` = elevated-1 background with label text; `muted` = elevated-2 background with placeholder-tone text for secondary shortcuts. Both carry a 0.5px stroke and the hard 2px bottom edge Figma draws on the key cap. Reflected. |
69
- | `inset` | `inset` | `boolean` | `false` | Pressed look: border-strong stroke, 1px downward nudge and (muted variant) a darker fill. Reflected. |
70
-
71
- ##### Deprecated (still supported — removal targeted for 3.0)
72
-
73
- | Property | Attribute | Type | Use instead |
74
- | --- | --- | --- | --- |
75
- | `pill` | `pill` | `boolean` | The Kbd spec has a single 4px radius at every size (audit 16); `pill` is kept working as an alias but logs a one-time notice. |
76
-
77
- ### Events
78
-
79
- | Event | Detail | Bubbles / composed | Description |
80
- | --- | --- | --- | --- |
81
- | — | — | — | This element emits no custom events. |
82
-
83
- ### Slots
84
-
85
- | Slot | Description |
86
- | --- | --- |
87
- | (default) | The key label (e.g. `Ctrl`, `K`, `⌘`) |
88
-
89
- ### CSS Parts
90
-
91
- | Part | Description |
92
- | --- | --- |
93
- | — | None exposed. |
94
-
95
- ### `<rel-kbd-group>`
96
-
97
- #### Attributes / Properties
98
-
99
- | Property | Attribute | Type | Default | Description |
100
- | --- | --- | --- | --- | --- |
101
- | `items` | `items` | `string[]` | `[]` | Key labels to render, one `<rel-kbd>` each, joined by `+` separators. Set as a property or as a JSON array attribute (`items='["Ctrl","K"]'`). |
102
- | `size` | `size` | `"sm" \| "md" \| "lg" \| "small" \| "medium" \| "large"` | `"md"` | Passed through to every generated <rel-kbd>: `small` / `medium` / `large` (legacy `sm` / `md` / `lg` still accepted). Reflected. |
103
- | `variant` | `variant` | `"default" \| "muted"` | `"default"` | Passed through to every generated <rel-kbd>: `default` or `muted`. Reflected. |
104
-
105
- ### Events
106
-
107
- | Event | Detail | Bubbles / composed | Description |
108
- | --- | --- | --- | --- |
109
- | — | — | — | This element emits no custom events. |
110
-
111
- ### Slots
112
-
113
- | Slot | Description |
114
- | --- | --- |
115
- | (default) | Extra content rendered after the generated keys (e.g. hand-written `<rel-kbd>` children) |
116
-
117
- ### CSS Parts
118
-
119
- | Part | Description |
120
- | --- | --- |
121
- | `label` | The `+` separator between generated keys |
122
- | `item` | Each generated `<rel-kbd>` key cap |
123
-
124
- <!-- readme-gen:end -->
125
-
126
- ## Accessibility
127
-
128
- - Both elements are purely presentational: no ARIA role, no `tabindex`, no keyboard handling and no events. `<rel-kbd>` renders only its default slot, so the key label is plain text for screen readers.
129
- - Neither element wraps its content in a native `<kbd>`. If you need that semantics, put the `<kbd>` in light DOM: `<kbd><rel-kbd>Ctrl</rel-kbd></kbd>`.
130
- - In `<rel-kbd-group>` the "+" separators are `aria-hidden="true"`, so a shortcut reads as the sequence of key labels only.
131
- - Text is `user-select: none` on the key caps and separators, so shortcuts are not copied along with surrounding prose.
132
- - Colours come from the neutral elevated backgrounds with `--rel-text-label` (default) and `--rel-text-placeholder` (muted) text; the muted variant is intended for secondary shortcuts and has lower contrast by design.
133
-
134
- ## Notes / Edge Cases
135
-
136
- - Heights are the Figma frame heights (20 / 24 / 28px) with the 0.5px stroke inside them (`box-sizing: border-box`), and the corner radius is 4px at every size. The cap carries a hard 2px bottom edge (a zero-blur drop shadow), so it occupies 2px more vertical space than its nominal height.
137
- - `small` / `medium` / `large` and `sm` / `md` / `lg` are interchangeable at the CSS level (`:host([size="md"])` and `:host([size="medium"])` share rules); the default value is `md`.
138
- - `inset` swaps the stroke to `--rel-border-strong` and nudges the cap 1px down; in the `muted` variant it also darkens the fill.
139
- - A `<span>` slotted into `<rel-kbd>` picks up body-sm-regular type (Figma hint text) instead of the label type.
140
- - `<rel-kbd-group>` passes its `size` and `variant` to every generated key; `items` set as an attribute must be a JSON array string. Slotted `<rel-kbd>` children render after the generated keys with no automatic "+" separators — either use `items` or hand-write the whole shortcut.
141
- - The `item` and `label` parts exist only on `<rel-kbd-group>`; a standalone `<rel-kbd>` exposes no parts.
1
+ # rel-kbd
2
+
3
+ `<rel-kbd>` is the single key cap from the Figma "Kbd" component (node 6316:284): a flat, bordered chip that shows a keyboard key or shortcut inline with text, in three heights (20 / 24 / 28px) and two fills (`default`, `muted`), with an `inset` pressed look. `<rel-kbd-group>` (Figma Kbd Items=1–4) renders a multi-key shortcut from an `items` array, one `<rel-kbd>` per key joined by "+" separators. Use them in help text, tooltips, menus and command palettes to display shortcuts. They are display-only — do not use them as buttons, and use `rel-chip` for tags or `rel-badge` for counts.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Single key -->
9
+ <rel-kbd>K</rel-kbd>
10
+
11
+ <!-- Sizes -->
12
+ <rel-kbd size="small">Esc</rel-kbd>
13
+ <rel-kbd size="medium">Enter</rel-kbd>
14
+ <rel-kbd size="large">Space</rel-kbd>
15
+
16
+ <!-- Variants -->
17
+ <rel-kbd variant="default">Shift</rel-kbd>
18
+ <rel-kbd variant="muted">⌘</rel-kbd>
19
+
20
+ <!-- Pressed look -->
21
+ <p>Hold <rel-kbd inset>Space</rel-kbd> to preview</p>
22
+
23
+ <!-- Multi-key shortcut from an items array (JSON attribute or property) -->
24
+ <rel-kbd-group items='["Ctrl","Shift","P"]' size="medium"></rel-kbd-group>
25
+ <rel-kbd-group id="palette" variant="muted" size="small"></rel-kbd-group>
26
+ <script>
27
+ document.getElementById("palette").items = ["⌘", "K"];
28
+ </script>
29
+
30
+ <!-- Inline with text -->
31
+ <p>Press <rel-kbd-group items='["mod","K"]'></rel-kbd-group> to search</p>
32
+ ```
33
+
34
+ ### Named keys and Mac symbols (new in 1.5.0)
35
+
36
+ `key-name` on `<rel-kbd>` and every entry of `items` on `<rel-kbd-group>` take a named key. Named keys follow the viewer's platform: Mac shows the symbols (⌘ ⌃ ⌥ ⇧ ↩ ⎋ ⇥ ⌫ ⌦ ⇞ ⇟ ↖ ↘ ⇪), every other platform the short words (Ctrl, Alt, Shift, Enter, Esc, Tab, Backspace, Delete, PgUp, PgDn, Home, End, Caps Lock). `mod` is the primary modifier: ⌘ on Mac, Ctrl elsewhere. Slotted text is never reinterpreted.
37
+
38
+ ```html
39
+ <!-- ⌘ K on a Mac, Ctrl + K elsewhere; read as "Command plus K" / "Control plus K" -->
40
+ <rel-kbd-group items='["mod","K"]'></rel-kbd-group>
41
+
42
+ <!-- A single named key -->
43
+ <rel-kbd key-name="shift"></rel-kbd>
44
+
45
+ <!-- Force a convention (default "auto" detects it from the browser) -->
46
+ <rel-kbd-group items='["mod","Shift","P"]' platform="mac"></rel-kbd-group>
47
+ <rel-kbd key-name="option" platform="other"></rel-kbd> <!-- Alt -->
48
+
49
+ <!-- Slotted text renders exactly as written -->
50
+ <rel-kbd>Ctrl</rel-kbd>
51
+ ```
52
+
53
+ | `key-name` (any case) | Mac | Elsewhere | Read as |
54
+ | --- | --- | --- | --- |
55
+ | `mod` | ⌘ | Ctrl | Command / Control |
56
+ | `cmd`, `command` | ⌘ | ⌘ | Command |
57
+ | `meta` | ⌘ | Win | Command / Windows |
58
+ | `ctrl`, `control` | ⌃ | Ctrl | Control |
59
+ | `alt`, `option`, `opt` | ⌥ | Alt | Option / Alt |
60
+ | `shift` | ⇧ | Shift | Shift |
61
+ | `enter`, `return` | ↩ | Enter | Return / Enter |
62
+ | `esc`, `escape` | ⎋ | Esc | Escape |
63
+ | `tab` | ⇥ | Tab | Tab |
64
+ | `backspace` | ⌫ | Backspace | Backspace |
65
+ | `delete` | ⌦ | Delete | Delete |
66
+ | `space` | Space | Space | Space |
67
+ | `up`, `down`, `left`, `right` | ↑ ↓ ← → | ↑ ↓ ← → | Up Arrow… |
68
+ | `pageup`, `pagedown` | ⇞ ⇟ | PgUp, PgDn | Page Up / Page Down |
69
+ | `home`, `end` | ↖ ↘ | Home, End | Home / End |
70
+ | `capslock` | ⇪ | Caps Lock | Caps Lock |
71
+
72
+ Anything else (`K`, `F5`, `⌘`) is shown as typed.
73
+
74
+ ### Deprecated aliases
75
+
76
+ ```html
77
+ <!-- sm / md / lg → small / medium / large (accepted silently; no console notice) -->
78
+ <rel-kbd size="sm">S</rel-kbd>
79
+ <rel-kbd size="md">M</rel-kbd>
80
+ <rel-kbd size="lg">L</rel-kbd>
81
+ <rel-kbd-group items='["Ctrl","C"]' size="md"></rel-kbd-group>
82
+
83
+ <!-- `pill` is deprecated → use the default 4px radius. Still renders fully rounded corners and logs once:
84
+ [rel-kbd] "pill" is deprecated and will be removed in 3.0 — use "the default radius (4px at every size)" instead. The Kbd spec has one radius at every size; pill keeps working but is not part of the design. -->
85
+ <rel-kbd pill>R</rel-kbd>
86
+ ```
87
+
88
+ <!-- readme-gen:start -->
89
+
90
+ <!-- Generated from rel-kbd.ts — do not edit; run readme-generate.mjs -->
91
+
92
+ ## Elements
93
+
94
+ | Element | Class | Source |
95
+ | --- | --- | --- |
96
+ | `<rel-kbd>` | `RelKbd` | `rel-kbd.ts` |
97
+ | `<rel-kbd-group>` | `RelKbdGroup` | `rel-kbd.ts` |
98
+
99
+ ## API
100
+
101
+ ### `<rel-kbd>`
102
+
103
+ #### Attributes / Properties
104
+
105
+ | Property | Attribute | Type | Default | Description |
106
+ | --- | --- | --- | --- | --- |
107
+ | `keyName` | `key-name` | `string` | `undefined` | New in 1.5.0. A named key, drawn in the platform's convention instead of the slotted text: `mod` (⌘ on Mac, Ctrl elsewhere), `cmd` / `command` / `meta`, `ctrl` / `control`, `alt` / `option` / `opt`, `shift`, `enter` / `return`, `esc` / `escape`, `tab`, `backspace`, `delete`, `space`, `up` / `down` / `left` / `right`, `pageup` / `pagedown`, `home` / `end`, `capslock` (case-insensitive). Mac shows symbols (⌘ ⌃ ⌥ ⇧ ↩ ⎋ ⇥ ⌫ ⌦ ⇞ ⇟ ↖ ↘ ⇪); elsewhere the short words (Ctrl, Alt, Esc, PgUp…); arrows are ↑ ↓ ← → on both and Space is the word on both. The symbol is hidden from assistive technology and the key's full name (Command, Option…) is read instead. Any other value is shown as typed. While set, slotted content is not rendered. |
108
+ | `platform` | `platform` | `"auto" \| "mac" \| "other"` | `"auto"` | New in 1.5.0. Keyboard convention for `key-name`: `auto` detects Mac / iPhone / iPad from the browser (no `navigator`, as in SSR, counts as `other`), `mac` and `other` force one. Has no effect on slotted text. |
109
+ | `size` | `size` | `"sm" \| "md" \| "lg" \| "small" \| "medium" \| "large"` | `"md"` | Key-cap scale (Figma Size): `small` 20px tall / label-sm, `medium` 24px / label-md, `large` 28px / label-lg; 4px radius at every size. A single-symbol key (⌘ ⌥ ⇧ ⌃, `mod` when it shows ⌘, arrows…) is a square cap, 20 × 20 / 24 × 24 / 28 × 28px, with the symbol centred (new in 1.5.0). `sm` / `md` / `lg` are the legacy short spellings and stay accepted. Reflected. |
110
+ | `variant` | `variant` | `"default" \| "muted"` | `"default"` | Fill / text contrast: `default` = elevated-1 background with label text; `muted` = elevated-2 background with caption-tone text for secondary shortcuts. Both carry a 0.5px stroke and the hard 2px bottom edge Figma draws on the key cap. Reflected. |
111
+ | `inset` | `inset` | `boolean` | `false` | Pressed look: border-strong stroke and a 1px downward nudge; the fill stays the variant's. Reflected. |
112
+
113
+ ##### Deprecated (still supported — removal targeted for 3.0)
114
+
115
+ | Property | Attribute | Type | Use instead |
116
+ | --- | --- | --- | --- |
117
+ | `pill` | `pill` | `boolean` | The Kbd spec has a single 4px radius at every size (audit 16); `pill` is kept working as an alias but logs a one-time notice. |
118
+
119
+ ### Events
120
+
121
+ | Event | Detail | Bubbles / composed | Description |
122
+ | --- | --- | --- | --- |
123
+ | — | — | — | This element emits no custom events. |
124
+
125
+ ### Slots
126
+
127
+ | Slot | Description |
128
+ | --- | --- |
129
+ | (default) | The key label (e.g. `Ctrl`, `K`, `⌘`), rendered exactly as written. Not rendered while `key-name` is set. |
130
+
131
+ ### CSS Parts
132
+
133
+ | Part | Description |
134
+ | --- | --- |
135
+ | — | None exposed. |
136
+
137
+ ### `<rel-kbd-group>`
138
+
139
+ #### Attributes / Properties
140
+
141
+ | Property | Attribute | Type | Default | Description |
142
+ | --- | --- | --- | --- | --- |
143
+ | `items` | `items` | `string[]` | `[]` | Keys to render, one `<rel-kbd>` each, joined by `+` separators (read as "plus"). Set as a property or as a JSON array attribute (`items='["mod","K"]'`). Since 1.5.0 each entry is a `key-name`: named keys (`mod`, `ctrl`, `shift`, `enter`, arrows…, case-insensitive) follow the platform convention, so `"Ctrl"` shows ⌃ on a Mac; use `"mod"` for the primary modifier (⌘ on Mac, Ctrl elsewhere). Anything else is shown as typed. |
144
+ | `platform` | `platform` | `"auto" \| "mac" \| "other"` | `"auto"` | New in 1.5.0. Passed through to every generated <rel-kbd>: `auto` (default) detects Mac from the browser, `mac` / `other` force a convention for named keys. |
145
+ | `size` | `size` | `"sm" \| "md" \| "lg" \| "small" \| "medium" \| "large"` | `"md"` | Passed through to every generated <rel-kbd>: `small` / `medium` / `large` (legacy `sm` / `md` / `lg` still accepted). Reflected. |
146
+ | `variant` | `variant` | `"default" \| "muted"` | `"default"` | Passed through to every generated <rel-kbd>: `default` or `muted`. Reflected. |
147
+
148
+ ### Events
149
+
150
+ | Event | Detail | Bubbles / composed | Description |
151
+ | --- | --- | --- | --- |
152
+ | — | — | — | This element emits no custom events. |
153
+
154
+ ### Slots
155
+
156
+ | Slot | Description |
157
+ | --- | --- |
158
+ | (default) | Extra content rendered after the generated keys (e.g. hand-written `<rel-kbd>` children) |
159
+
160
+ ### CSS Parts
161
+
162
+ | Part | Description |
163
+ | --- | --- |
164
+ | `label` | The `+` separator between generated keys |
165
+ | `item` | Each generated `<rel-kbd>` key cap |
166
+
167
+ <!-- readme-gen:end -->
168
+
169
+ ## Accessibility
170
+
171
+ - Both elements are purely presentational: no ARIA role, no `tabindex`, no keyboard handling and no events. Slotted key labels are plain text for screen readers.
172
+ - Named keys (`key-name`, and `items` entries): when the cap shows a symbol or abbreviation (⌘, ⌥, Ctrl, Esc, PgUp, ↑), it is `aria-hidden` and the key's full name (Command, Option, Control, Escape, Page Up, Up Arrow) is rendered as visually hidden text instead. The names are English.
173
+ - Neither element wraps its content in a native `<kbd>`. If you need that semantics, put the `<kbd>` in light DOM: `<kbd><rel-kbd>Ctrl</rel-kbd></kbd>`.
174
+ - In `<rel-kbd-group>` the visible "+" separators are `aria-hidden="true"` and a visually hidden "plus" is read in their place (since 1.5.0), so `items='["mod","K"]'` reads "Command plus K" on a Mac and "Control plus K" elsewhere.
175
+ - Text is `user-select: none` on the key caps and separators, so shortcuts are not copied along with surrounding prose.
176
+ - Colours come from the neutral elevated backgrounds with `--rel-text-label` (default) and `--rel-text-caption` (muted) text. The muted variant is for secondary shortcuts: quieter than the default, but its label still meets AA (about 5.7:1 in light mode, 5.8:1 in dark).
177
+
178
+ ## Notes / Edge Cases
179
+
180
+ - Heights are the Figma frame heights (20 / 24 / 28px) with the 0.5px stroke inside them (`box-sizing: border-box`), and the corner radius is 4px at every size. The cap carries a hard 2px bottom edge (a zero-blur drop shadow), so it occupies 2px more vertical space than its nominal height.
181
+ - `small` / `medium` / `large` and `sm` / `md` / `lg` are interchangeable at the CSS level (`:host([size="md"])` and `:host([size="medium"])` share rules); the default value is `md`.
182
+ - `inset` swaps the stroke to `--rel-border-strong` and nudges the cap 1px down; in the `muted` variant it also darkens the fill.
183
+ - A `<span>` slotted into `<rel-kbd>` picks up body-sm-regular type (Figma hint text) instead of the label type.
184
+ - `<rel-kbd-group>` passes its `size` and `variant` to every generated key; `items` set as an attribute must be a JSON array string. Slotted `<rel-kbd>` children render after the generated keys with no automatic "+" separators — either use `items` or hand-write the whole shortcut.
185
+ - The `item` and `label` parts exist only on `<rel-kbd-group>`; a standalone `<rel-kbd>` exposes no parts.
186
+ - Since 1.5.0 `items` entries are named keys, so on a Mac `items='["Ctrl","Shift","P"]'` shows ⌃ ⇧ P (Control is a real Mac key). Use `"mod"` where you mean "Cmd on Mac, Ctrl elsewhere", or pass `platform="other"` to keep the words everywhere. Elsewhere, `"Escape"` now shows as Esc and `"PageUp"` as PgUp; plain words that are not named keys are unchanged.
187
+ - `platform="auto"` reads `navigator.userAgentData.platform`, then `navigator.platform`. Server-rendered markup has no navigator and resolves to `other`, so a Mac viewer sees Ctrl until the element renders in the browser. Unknown `platform` values behave as `auto`.
188
+ - No Figma guidance exists for Mac symbols (the Kbd component has Size, Variant and Inset only, checked 2026-10-09), so a symbol cap is an ordinary cap: same heights, same side padding as text (a ⌘ cap is about 30 / 33 / 43px wide at small / medium / large), not a narrower square.
@@ -39,40 +39,40 @@ A responsive CSS Grid layout component with automatic breakpoint handling. Provi
39
39
  </rel-layout>
40
40
  ```
41
41
 
42
- <!-- readme-gen:start -->
43
-
44
- <!-- Generated from rel-layout.ts — do not edit; run readme-generate.mjs -->
45
-
46
- ## API
47
-
48
- ### Attributes / Properties
49
-
50
- | Property | Attribute | Type | Default | Description |
51
- | --- | --- | --- | --- | --- |
52
- | `gap` | `gap` | `string` | `"1rem"` | — |
53
- | `columns` | `columns` | `number` | `4` | — |
54
- | `responsive` | `responsive` | `boolean` | `true` | Reflected. |
55
-
56
- ## Events
57
-
58
- | Event | Detail | Bubbles / composed | Description |
59
- | --- | --- | --- | --- |
60
- | — | — | — | This element emits no custom events. |
61
-
62
- ## Slots
63
-
64
- | Slot | Description |
65
- | --- | --- |
66
- | (default) | Main content. |
67
-
68
- ## CSS Parts
69
-
70
- | Part | Description |
71
- | --- | --- |
72
- | — | None exposed. |
73
-
74
- <!-- readme-gen:end -->
75
-
42
+ <!-- readme-gen:start -->
43
+
44
+ <!-- Generated from rel-layout.ts — do not edit; run readme-generate.mjs -->
45
+
46
+ ## API
47
+
48
+ ### Attributes / Properties
49
+
50
+ | Property | Attribute | Type | Default | Description |
51
+ | --- | --- | --- | --- | --- |
52
+ | `gap` | `gap` | `string` | `"1rem"` | — |
53
+ | `columns` | `columns` | `number` | `4` | — |
54
+ | `responsive` | `responsive` | `boolean` | `true` | Reflected. |
55
+
56
+ ## Events
57
+
58
+ | Event | Detail | Bubbles / composed | Description |
59
+ | --- | --- | --- | --- |
60
+ | — | — | — | This element emits no custom events. |
61
+
62
+ ## Slots
63
+
64
+ | Slot | Description |
65
+ | --- | --- |
66
+ | (default) | Main content. |
67
+
68
+ ## CSS Parts
69
+
70
+ | Part | Description |
71
+ | --- | --- |
72
+ | — | None exposed. |
73
+
74
+ <!-- readme-gen:end -->
75
+
76
76
  ## API
77
77
 
78
78
  ### Attributes/Properties
@@ -1,6 +1,6 @@
1
1
  # rel-menu
2
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>`.
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 four `type` row shapes: plain single-select rows (`list`, the default), checkbox rows, radio-style `select-option` rows, or `arrow` rows that open a submenu flyout; `width` picks the sizing mode (`fixed` or `fit`) independently. 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
4
 
5
5
  ## Usage
6
6
 
@@ -19,9 +19,10 @@
19
19
  <!-- Rows with submenu flyouts -->
20
20
  <rel-menu id="file" type="arrow"></rel-menu>
21
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>
22
+ <!-- Sizing modes: both 300px wide (override with --rel-menu-width); fixed caps the height at
23
+ --rel-menu-height (500px) and scrolls, fit hugs its rows. Combines with any type. -->
24
+ <rel-menu width="fixed" style="--rel-menu-width: 240px"></rel-menu>
25
+ <rel-menu type="checkbox" width="fit"></rel-menu>
25
26
 
26
27
  <!-- rel-menu-item is a registered placeholder: it renders nothing and rel-menu does not read it yet -->
27
28
  <rel-menu-item label="Rename" value="rename" icon="settings"></rel-menu-item>
@@ -84,10 +85,16 @@ actions.items = [...actions.items, { label: "Duplicate" }];
84
85
 
85
86
  | Property | Attribute | Type | Default | Description |
86
87
  | --- | --- | --- | --- | --- |
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
+ | `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 leading radio (`role="menuitemradio"`). `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
89
  | `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
90
  | `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
+ | `items` | `items` | `MenuItem[]` | `[]` | The rows to render, in order. Each entry is a `MenuItem` (`label`, optional `active`, `checked`, `disabled`, `submenu`, `open`, and, new in 1.5.0, `icon`). The array is copied on assignment, so mutate and reassign it to update the menu. |
92
+
93
+ #### Methods
94
+
95
+ | Method | Signature | Description |
96
+ | --- | --- | --- |
97
+ | `focusItem` | `focusItem(index: number)` | New in 1.5.0. Moves the virtual focus (the row `aria-activedescendant` names) to `index`, clamped to the rows; a negative index counts from the end, so `-1` is the last row. It moves neither DOM focus nor the ring: the row ring still follows the list's own keyboard focus. A menu button uses it to open on the first row (Enter, Space, ArrowDown) or the last (ArrowUp). |
91
98
 
92
99
  ### Events
93
100
 
@@ -143,11 +150,11 @@ actions.items = [...actions.items, { label: "Duplicate" }];
143
150
 
144
151
  ## Accessibility
145
152
 
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.
153
+ - 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, while the list has keyboard focus (`:focus-visible`), highlighted with a 2px `--rel-border-focus` outline inset 2px. There is no ring at rest or after a mouse click: the selected row is shown by its fill only, as in Figma.
147
154
  - 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
155
  - Disabled rows have `aria-disabled="true"`, render at 40% opacity with a `not-allowed` cursor and ignore clicks and Enter / Space.
149
156
  - 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`.
157
+ - The container shows a 2px `--rel-border-focus` outline (no offset) on `:focus-visible`.
151
158
  - No live-region announcements are made.
152
159
 
153
160
  | Key (virtual focus in the main list) | Action |
@@ -168,13 +175,13 @@ actions.items = [...actions.items, { label: "Duplicate" }];
168
175
  ## Notes / Edge Cases
169
176
 
170
177
  - **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).
178
+ - `MenuItem` shape: `{ label: string; icon?: 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). `icon` (new in 1.5.0) is a `rel-icon` name drawn before the label on `list` and `arrow` rows, at 20 / 18 / 16px for the large / medium / small sizes; checkbox and select-option rows ignore it.
172
179
  - 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
180
  - 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
181
  - `size` is reflected as an attribute and the row rules key off `rel-menu[size="…"]`; submenu rows follow the same size.
175
182
  - `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
183
  - `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`.
184
+ - The flyout opens in the browser top layer (Popover API, `popover="manual"`), so no ancestor clips it — not the menu's own scroller in `width="fixed"`, a card, a `rel-modal` or a scrolling sidebar (changed in 1.5.0; it used to be absolutely positioned inside its row and was cut off by all of those). It sits flush beside its row: to the right when it fits, flipped to the left when it would run off the right edge, shifted up when it would run past the bottom, and kept 8px inside the viewport. On an outside scroll it follows its row while the row is visible and closes once the row scrolls out of view. Without the Popover API it falls back to the old `left: 100%` placement.
178
185
  - `--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
186
  - `<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
187
  - This module imports `rel-checkbox`, `rel-radio` and `rel-icon`, so those elements are registered whenever `rel-menu` is loaded.