@reliability-design/web 1.4.8 → 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.
- package/CHANGELOG.md +214 -0
- package/custom-elements.json +18600 -0
- package/dist/components/rel-accordion/README.md +9 -2
- package/dist/components/rel-alert/README.md +5 -8
- package/dist/components/rel-autocomplete/README.md +209 -208
- package/dist/components/rel-avatar/README.md +228 -118
- package/dist/components/rel-breadcrumb/README.md +1 -0
- package/dist/components/rel-button/README.md +9 -9
- package/dist/components/rel-calendar/README.md +111 -109
- package/dist/components/rel-cardmedia/README.md +1 -1
- package/dist/components/rel-carousel/README.md +187 -186
- package/dist/components/rel-checkbox/README.md +159 -146
- package/dist/components/rel-chip/README.md +141 -138
- package/dist/components/rel-container/README.md +1 -1
- package/dist/components/rel-date-picker/README.md +221 -200
- package/dist/components/rel-drawer/README.md +4 -4
- package/dist/components/rel-kbd/README.md +188 -141
- package/dist/components/rel-layout/README.md +34 -34
- package/dist/components/rel-menu/README.md +17 -10
- package/dist/components/rel-menubar/README.md +218 -218
- package/dist/components/rel-otp/README.md +4 -8
- package/dist/components/rel-pagination/README.md +141 -100
- package/dist/components/rel-popover/README.md +220 -203
- package/dist/components/rel-radio/README.md +142 -131
- package/dist/components/rel-range-picker/README.md +194 -165
- package/dist/components/rel-resizable/README.md +220 -199
- package/dist/components/rel-segmented-button/README.md +158 -156
- package/dist/components/rel-select/README.md +22 -16
- package/dist/components/rel-sheet/README.md +3 -2
- package/dist/components/rel-signature-pad/README.md +161 -0
- package/dist/components/rel-slider/README.md +140 -131
- package/dist/components/rel-snackbar/README.md +170 -168
- package/dist/components/rel-split-button/README.md +129 -0
- package/dist/components/rel-stepper/README.md +171 -162
- package/dist/components/rel-switch/README.md +122 -117
- package/dist/components/rel-tab/README.md +184 -173
- package/dist/components/rel-textfield/README.md +23 -30
- package/dist/components/rel-time-picker/README.md +188 -164
- package/dist/components/rel-toast/README.md +20 -11
- package/dist/components/rel-tooltip/README.md +5 -4
- package/dist/components/rel-tree/README.md +157 -0
- package/dist/components/rel-upload/README.md +8 -5
- package/dist/index.d.mts +1698 -607
- package/dist/index.d.ts +1698 -607
- package/dist/index.js +12276 -6347
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12218 -6296
- package/dist/index.mjs.map +1 -1
- package/dist/styles/motion.css +31 -0
- package/dist/styles/motion.tokens.json +38 -0
- package/dist/styles/vars.css +88 -64
- package/dist/{vars-DXX6QOAG.css → vars-E22LYFMV.css} +88 -64
- package/package.json +60 -37
- package/dist/styles/focus-ring.ts +0 -84
|
@@ -1,168 +1,170 @@
|
|
|
1
|
-
# rel-snackbar
|
|
2
|
-
|
|
3
|
-
`<rel-snackbar>` is the snackbar of the Reliability Design System (Figma "Snackbar"): a dark, elevated message bar with a 4px tone accent and leading status icon for the success / warning / destructive tones, an optional action button and a close icon, in single-line and double-line (Figma Type=Longer Action) layouts. It is shown by setting `show` and hides itself after `duration` milliseconds. Unlike `<rel-toast>` it is **not** positioned — it is a `display: block` element you place yourself (in-flow, or fixed via your own CSS). Use it for brief feedback with one follow-up action ("Undo", "Retry"); use `<rel-alert>` for messages that must stay on the page.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<!-- Hidden until `show` is set -->
|
|
9
|
-
<rel-snackbar id="uploaded" message="File uploaded"></rel-snackbar>
|
|
10
|
-
|
|
11
|
-
<!-- Initially visible; neutral tone (no accent, no icon), auto-hides after 4000 ms -->
|
|
12
|
-
<rel-snackbar show message="Settings saved"></rel-snackbar>
|
|
13
|
-
|
|
14
|
-
<!-- Status tones: left accent + leading icon -->
|
|
15
|
-
<rel-snackbar show tone="success" message="Invitation sent"></rel-snackbar>
|
|
16
|
-
<rel-snackbar show tone="warning" message="Connection is unstable"></rel-snackbar>
|
|
17
|
-
<rel-snackbar show tone="destructive" message="Payment failed"></rel-snackbar>
|
|
18
|
-
|
|
19
|
-
<!-- Action button -->
|
|
20
|
-
<rel-snackbar id="deleted" message="Item deleted" action="Undo"></rel-snackbar>
|
|
21
|
-
|
|
22
|
-
<!-- Double-line layout with a longer (2 × duration) dismiss delay -->
|
|
23
|
-
<rel-snackbar
|
|
24
|
-
id="archived"
|
|
25
|
-
message="12 conversations were archived and will be deleted in 30 days"
|
|
26
|
-
action="Undo"
|
|
27
|
-
variant="longer-action"
|
|
28
|
-
></rel-snackbar>
|
|
29
|
-
|
|
30
|
-
<!--
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<rel-snackbar
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
<!--
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
| `
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
| `
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
- `
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
- `
|
|
1
|
+
# rel-snackbar
|
|
2
|
+
|
|
3
|
+
`<rel-snackbar>` is the snackbar of the Reliability Design System (Figma "Snackbar"): a dark, elevated message bar with a 4px tone accent and leading status icon for the success / warning / destructive tones, an optional action button and a close icon, in single-line and double-line (Figma Type=Longer Action) layouts. It is shown by setting `show` and hides itself after `duration` milliseconds. Unlike `<rel-toast>` it is **not** positioned — it is a `display: block` element you place yourself (in-flow, or fixed via your own CSS). Use it for brief feedback with one follow-up action ("Undo", "Retry"); use `<rel-alert>` for messages that must stay on the page.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Hidden until `show` is set -->
|
|
9
|
+
<rel-snackbar id="uploaded" message="File uploaded"></rel-snackbar>
|
|
10
|
+
|
|
11
|
+
<!-- Initially visible; neutral tone (no accent, no icon), auto-hides after 4000 ms -->
|
|
12
|
+
<rel-snackbar show message="Settings saved"></rel-snackbar>
|
|
13
|
+
|
|
14
|
+
<!-- Status tones: left accent + leading icon -->
|
|
15
|
+
<rel-snackbar show tone="success" message="Invitation sent"></rel-snackbar>
|
|
16
|
+
<rel-snackbar show tone="warning" message="Connection is unstable"></rel-snackbar>
|
|
17
|
+
<rel-snackbar show tone="destructive" message="Payment failed"></rel-snackbar>
|
|
18
|
+
|
|
19
|
+
<!-- Action button -->
|
|
20
|
+
<rel-snackbar id="deleted" message="Item deleted" action="Undo"></rel-snackbar>
|
|
21
|
+
|
|
22
|
+
<!-- Double-line layout with a longer (2 × duration) dismiss delay -->
|
|
23
|
+
<rel-snackbar
|
|
24
|
+
id="archived"
|
|
25
|
+
message="12 conversations were archived and will be deleted in 30 days"
|
|
26
|
+
action="Undo"
|
|
27
|
+
variant="longer-action"
|
|
28
|
+
></rel-snackbar>
|
|
29
|
+
|
|
30
|
+
<!-- Persistent, without the close icon ("false" switches a default-true boolean off, since 1.5.0) -->
|
|
31
|
+
<rel-snackbar id="busy" message="Processing…" duration="0" icon-close="false"></rel-snackbar>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
const uploaded = document.getElementById("uploaded");
|
|
36
|
+
uploaded.show = true; // starts the auto-dismiss timer and announces the message
|
|
37
|
+
uploaded.addEventListener("close", () => {
|
|
38
|
+
uploaded.show; // false — fired by the close icon, the action button and the timer
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const deleted = document.getElementById("deleted");
|
|
42
|
+
deleted.addEventListener("actionClick", () => {
|
|
43
|
+
// undo the deletion… the snackbar dismisses itself right after (a `close` event follows)
|
|
44
|
+
});
|
|
45
|
+
deleted.show = true;
|
|
46
|
+
|
|
47
|
+
const busy = document.getElementById("busy");
|
|
48
|
+
busy.show = true;
|
|
49
|
+
busy.show = false; // hides silently — no `close` event when hidden from script
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
/* The component is display: block; position it yourself */
|
|
54
|
+
rel-snackbar {
|
|
55
|
+
position: fixed;
|
|
56
|
+
bottom: 24px;
|
|
57
|
+
left: 50%;
|
|
58
|
+
transform: translateX(-50%);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Deprecated aliases
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<!-- type= is the deprecated alias of tone= (tone wins when both are set). Logs once per page:
|
|
66
|
+
[rel-snackbar] "type" is deprecated and will be removed in 3.0 — use "tone" instead. Note: tone="destructive" replaces type="error"; tone="neutral" replaces type="default". -->
|
|
67
|
+
<rel-snackbar type="error" message="Payment failed"></rel-snackbar>
|
|
68
|
+
<rel-snackbar type="default" message="Settings saved"></rel-snackbar>
|
|
69
|
+
|
|
70
|
+
<!-- tone="default" is the deprecated spelling of tone="neutral". Logs once:
|
|
71
|
+
[rel-snackbar] "tone="default"" is deprecated and will be removed in 3.0 — use "tone="neutral"" instead. -->
|
|
72
|
+
<rel-snackbar tone="default" message="Settings saved"></rel-snackbar>
|
|
73
|
+
|
|
74
|
+
<!-- tone="error" | "danger" | "critical" are deprecated spellings of tone="destructive". Logs once per spelling:
|
|
75
|
+
[rel-snackbar] "tone="error"" is deprecated and will be removed in 3.0 — use "tone="destructive"" instead. -->
|
|
76
|
+
<rel-snackbar tone="error" message="Payment failed"></rel-snackbar>
|
|
77
|
+
<rel-snackbar tone="critical" message="Payment failed"></rel-snackbar>
|
|
78
|
+
|
|
79
|
+
<!-- lines="double" and longeraction (lower-case attribute) are deprecated spellings of
|
|
80
|
+
variant="longer-action". Either one alone renders the full longer-action variant: stacked
|
|
81
|
+
layout and the doubled auto-dismiss delay. Ignored when variant is set; each logs once. -->
|
|
82
|
+
<rel-snackbar message="Older markup" action="Undo" lines="double"></rel-snackbar>
|
|
83
|
+
<rel-snackbar message="Older markup" action="Undo" longeraction></rel-snackbar>
|
|
84
|
+
|
|
85
|
+
<!-- iconclose → icon-close (since 1.5.0; still works, logs a one-time console notice, removed in 3.0) -->
|
|
86
|
+
<rel-snackbar message="Processing…" duration="0" iconclose="false"></rel-snackbar>
|
|
87
|
+
<rel-snackbar message="Processing…" duration="0" icon-close="false"></rel-snackbar>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
<!-- readme-gen:start -->
|
|
91
|
+
|
|
92
|
+
<!-- Generated from rel-snackbar.ts — do not edit; run readme-generate.mjs -->
|
|
93
|
+
|
|
94
|
+
## API
|
|
95
|
+
|
|
96
|
+
### Attributes / Properties
|
|
97
|
+
|
|
98
|
+
| Property | Attribute | Type | Default | Description |
|
|
99
|
+
| --- | --- | --- | --- | --- |
|
|
100
|
+
| `message` | `message` | `string` | `"This is a snackbar message"` | Message text. Announced to screen readers through the shared live-region announcer when the snackbar is shown and whenever it changes while shown. The default is a placeholder — always set it. |
|
|
101
|
+
| `action` | `action` | `string` | `undefined` | Label of the optional action button (Figma trailing button, Static / Small); omitted when unset. Clicking it fires `actionClick` and then dismisses the snackbar. |
|
|
102
|
+
| `variant` | `variant` | `"default" \| "longer-action"` | `undefined` | Layout and timing (Figma "Type"): `"default"` (the default: message and actions on one row) \| `"longer-action"` (message stacked above the actions, which align to the end, with the auto-dismiss delay doubled so there is time to use the action). Takes precedence over the deprecated `lines` and `longerAction` props. |
|
|
103
|
+
| `iconClose` | `icon-close` | `boolean` | `true` | Shows the trailing close icon button. Defaults to true; `icon-close="false"` (or the property set to `false`) hides the button. The `iconclose` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
104
|
+
| `duration` | `duration` | `number` | `4000` | Auto-dismiss delay in milliseconds (doubled by `variant="longer-action"`), started when `show` becomes true and restarted when `duration` or the layout changes while shown. `0` (or a negative value) disables auto-dismiss. |
|
|
105
|
+
| `tone` | `tone` | `"neutral" \| "success" \| "warning" \| "destructive" \| "default" \| "error" \| "danger" \| "critical"` | `undefined` | Semantic tone (Figma "Tone"): `"neutral"` (default: no accent, no icon) \| `"success"` \| `"warning"` \| `"destructive"` — the status tones add a 4px left accent and a leading icon (check-circle / warning / error) in the tone colour. `"default"` is a deprecated alias of `"neutral"`; `"error"`, `"danger"` and `"critical"` are deprecated aliases of `"destructive"`; each logs a one-time console notice. Takes precedence over the deprecated `type` prop. |
|
|
106
|
+
| `show` | `show` | `boolean` | `false` | Whether the snackbar is visible. Set it to true to show the snackbar and start the auto-dismiss timer; it is set back to false by the close icon, the action button and the timer. There is no open/close method — toggle this property. Reflected. |
|
|
107
|
+
|
|
108
|
+
#### Deprecated (still supported — removal targeted for 3.0)
|
|
109
|
+
|
|
110
|
+
| Property | Attribute | Type | Use instead |
|
|
111
|
+
| --- | --- | --- | --- |
|
|
112
|
+
| `longerAction` | `longeraction` | `boolean` | — use `variant="longer-action"`. On its own it renders the full longer-action variant (stacked layout and the doubled auto-dismiss delay, `duration * 2`). Ignored when `variant` is set. Logs a one-time console notice. |
|
|
113
|
+
| `lines` | `lines` | `"single" \| "double"` | — use `variant`; `lines="double"` maps to `variant="longer-action"` (stacked layout and the doubled auto-dismiss delay). Ignored when `variant` is set. Logs a one-time console notice. |
|
|
114
|
+
| `type` | `type` | `"neutral" \| "success" \| "warning" \| "destructive" \| "default" \| "error" \| "danger" \| "critical"` | Deprecated since 1.4.7 — alias of `tone`; use `tone`. Same values as `tone`; `type="error"` maps to `tone="destructive"` and `type="default"` to `tone="neutral"`. Ignored when `tone` is set. Logs a one-time console notice. |
|
|
115
|
+
|
|
116
|
+
### Public fields / accessors
|
|
117
|
+
|
|
118
|
+
| Name | Type | Description |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| `resolvedVariant` | `SnackbarVariant` | Read-only canonical layout actually rendered: explicit `variant` wins, else either deprecated prop (`lines="double"` or `longerAction`) promotes to `"longer-action"`, else `"default"`. |
|
|
121
|
+
| `resolvedTone` | `SnackbarTone` | Read-only canonical tone actually rendered: explicit `tone` wins, else `type`, else `"neutral"`; deprecated aliases are resolved to `"neutral"` / `"destructive"`. |
|
|
122
|
+
|
|
123
|
+
## Events
|
|
124
|
+
|
|
125
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
126
|
+
| --- | --- | --- | --- |
|
|
127
|
+
| `actionClick` | — | bubbles / composed | Fired when the action button is clicked, before the snackbar dismisses itself (a `close` event follows). No detail. |
|
|
128
|
+
| `close` | — | bubbles / composed | Fired whenever the snackbar dismisses itself — via the close icon, the action button or the auto-dismiss timer. Not fired when `show` is set to false from script. No detail. |
|
|
129
|
+
|
|
130
|
+
## Slots
|
|
131
|
+
|
|
132
|
+
| Slot | Description |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| — | This element has no slots. |
|
|
135
|
+
|
|
136
|
+
## CSS Parts
|
|
137
|
+
|
|
138
|
+
| Part | Description |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| `label` | The message text container |
|
|
141
|
+
| `action` | The action button; rendered only when `action` is set |
|
|
142
|
+
| `close-button` | The close icon button; rendered while `icon-close` is true |
|
|
143
|
+
|
|
144
|
+
<!-- readme-gen:end -->
|
|
145
|
+
|
|
146
|
+
## Accessibility
|
|
147
|
+
|
|
148
|
+
- The bar is always in the shadow DOM and hidden with `display: none` while `show` is false. Its role follows the tone: `role="alert"` for `destructive` (implicitly assertive), `role="status"` for every other tone (implicitly polite); no explicit `aria-live` is set. Because toggling `display` is not reliably announced, the component also pushes `message` into the shared off-screen live-region announcer (`utils/announce`) when `show` becomes true and whenever `message` changes while shown — assertively for `destructive`, politely otherwise. Focus is never moved.
|
|
149
|
+
- The leading status icon and the close glyph are `<rel-icon>`s and render `aria-hidden="true"`; the close control is a native `<button>` with `aria-label="Close"`, the action button is labelled by `action`. Both are in the Tab order; the component registers no key handlers (there is no Escape-to-close):
|
|
150
|
+
|
|
151
|
+
| Key | Action |
|
|
152
|
+
| --- | --- |
|
|
153
|
+
| Tab / Shift + Tab | Move between the action button (if any) and the close button (if any) |
|
|
154
|
+
| Enter / Space | Activate the focused button: action fires `actionClick` then `close`; the close button fires `close` |
|
|
155
|
+
|
|
156
|
+
- Keyboard focus on either button is a 2px `--rel-text-static-light` outline with 2px offset (`:focus-visible` only); the close button adds `--rel-border-radius-xs` corners, the action button keeps its pill radius.
|
|
157
|
+
- The 0.3s slide-up animation is disabled under `prefers-reduced-motion: reduce`.
|
|
158
|
+
- A snackbar that auto-dismisses while one of its buttons has focus drops focus to `<body>`; use `duration="0"` (or `variant="longer-action"`, which doubles the delay) when the action matters.
|
|
159
|
+
|
|
160
|
+
## Notes / Edge Cases
|
|
161
|
+
|
|
162
|
+
- Positioning is yours: the host is `display: block` and in flow. The bar itself is `min-width: 280px; max-width: 500px`.
|
|
163
|
+
- The auto-dismiss timer starts when `show` becomes true and restarts whenever `duration`, `variant` or a deprecated `lines` / `longerAction` changes while visible; `variant="longer-action"` doubles the delay (`duration * 2`). `duration="0"` disables it.
|
|
164
|
+
- Setting `show = false` from script hides the bar **without** firing `close`; `close` fires only for the close icon, the action button and the timer. Setting `show = true` on an already visible snackbar is a no-op (the value did not change).
|
|
165
|
+
- `variant="longer-action"` (Figma Longer Action) stacks the message over end-aligned actions with 16px top padding and doubles the auto-dismiss delay. The deprecated `lines="double"` and `longeraction` each produce the same full variant on their own (see "Deprecated aliases"); before 1.5.0 this README said each did only half of it.
|
|
166
|
+
- The status icon is fixed per tone (`check-circle`, `warning`, `error`) and neutral has none; there are no slots, so the icon cannot be replaced.
|
|
167
|
+
- `message` defaults to the placeholder "This is a snackbar message" — a snackbar that shows that text has simply not been given a message.
|
|
168
|
+
- `iconClose` is a boolean: presence or `""` means true, and since 1.5.0 `icon-close="false"` means false.
|
|
169
|
+
- Figma binds the success / destructive icon colours to dark-surface status text values that no light-mode semantic token resolves to; the component uses the status fill tokens (`--rel-bg-success` / `--rel-bg-danger` / `--rel-bg-warning`) for both the accent and the icon instead.
|
|
170
|
+
- `resolvedTone` is the tone actually rendered after alias resolution; use it (not `tone` / `type`) if you branch on tone in script.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# rel-split-button
|
|
2
|
+
|
|
3
|
+
<!-- @unreleased-component 1.5.0 -->
|
|
4
|
+
|
|
5
|
+
A button with a main action and a menu of related actions, also called a combo button. It is one pill in two segments with a 1px divider between them: the main action on the left, and a chevron on the right that opens a `rel-menu` of `items`, anchored below and end-aligned. Use it when one action is the usual choice and a few close variants should stay one click away, such as "New order" with "Duplicate" and "Save as template". Use `rel-button` for a single action, and a `rel-popover` with a `rel-menu` when no action is the default.
|
|
6
|
+
|
|
7
|
+
Each segment is a native `<button>` drawn with rel-button's own styles for the chosen `variant`, `tone` and `size`. The heights (32 / 40 / 48px), padding, type, hover, pressed, focus ring and disabled look are therefore rel-button's. The outer corners keep the pill radius and the seam between the segments is square. While the menu is open, the chevron keeps its pressed look and its arrow turns up.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<!-- Items are set as a property; the host's click is the main action -->
|
|
13
|
+
<rel-split-button id="order" label="New order"></rel-split-button>
|
|
14
|
+
<script>
|
|
15
|
+
const order = document.getElementById('order');
|
|
16
|
+
order.items = [
|
|
17
|
+
{ value: 'duplicate', label: 'Duplicate', icon: 'copy' },
|
|
18
|
+
{ value: 'template', label: 'Save as template' },
|
|
19
|
+
{ value: 'archive', label: 'Archive', disabled: true }
|
|
20
|
+
];
|
|
21
|
+
order.addEventListener('click', () => createOrder());
|
|
22
|
+
order.addEventListener('rel-select', (e) => {
|
|
23
|
+
console.log('chose', e.detail.value);
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<!-- Filled, in the brand colour, with a leading icon -->
|
|
28
|
+
<rel-split-button variant="primary" tone="brand" icon="plus" label="New order"></rel-split-button>
|
|
29
|
+
|
|
30
|
+
<!-- Small, and a custom name for the chevron -->
|
|
31
|
+
<rel-split-button size="small" menu-label="More export formats" label="Export CSV"></rel-split-button>
|
|
32
|
+
|
|
33
|
+
<!-- The main action is busy: a spinner only, and the chevron is disabled -->
|
|
34
|
+
<rel-split-button loading label="Saving"></rel-split-button>
|
|
35
|
+
|
|
36
|
+
<!-- Icon-only: the main action is a square; aria-label names it -->
|
|
37
|
+
<rel-split-button icon-only icon="plus" aria-label="New order"></rel-split-button>
|
|
38
|
+
|
|
39
|
+
<!-- On a dark or coloured surface -->
|
|
40
|
+
<rel-split-button variant="static" label="Book load"></rel-split-button>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`items` is an array, so set it as a property, or as a JSON array attribute in static HTML. In React 19 and Next.js, pass it as a prop on the client: server rendering drops arrays on custom elements.
|
|
44
|
+
|
|
45
|
+
The divider between the segments follows the variant:
|
|
46
|
+
|
|
47
|
+
- `secondary` draws the tone's outline border (`--rel-action-neutral-border-outline`, or the danger outline), which takes the outline's hover colour while the main action is hovered or pressed. The segments drop their inner borders.
|
|
48
|
+
- `primary` draws the segment's label colour.
|
|
49
|
+
- `static` draws the static label colour (white).
|
|
50
|
+
- `ghost` draws `--rel-border-subtle`.
|
|
51
|
+
|
|
52
|
+
The divider is its own 1px column, so the pill is the main action, plus 1px, plus the chevron. A disabled split button dims each segment and keeps the divider's colour.
|
|
53
|
+
|
|
54
|
+
<!-- readme-gen:start -->
|
|
55
|
+
|
|
56
|
+
<!-- Generated from rel-split-button.ts — do not edit; run readme-generate.mjs -->
|
|
57
|
+
|
|
58
|
+
## API
|
|
59
|
+
|
|
60
|
+
### Attributes / Properties
|
|
61
|
+
|
|
62
|
+
| Property | Attribute | Type | Default | Description |
|
|
63
|
+
| --- | --- | --- | --- | --- |
|
|
64
|
+
| `label` | `label` | `string` | `""` | Text of the main action. Slotted content replaces it. |
|
|
65
|
+
| `variant` | `variant` | `"primary" \| "secondary" \| "ghost" \| "static"` | `"secondary"` | Style of both segments, as rel-button's `variant`: `primary` (filled), `secondary` (outlined, the default), `ghost` (no fill or border) or `static` (transparent with a white label and divider, for dark or coloured surfaces; neutral only, as on rel-button). Reflected. |
|
|
66
|
+
| `tone` | `tone` | `"neutral" \| "brand" \| "destructive"` | `"neutral"` | Colour of both segments, as rel-button's `tone`: `neutral` (default), `brand` or `destructive`. As on rel-button, `brand` changes only the `primary` style. Reflected. |
|
|
67
|
+
| `size` | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Height of the pill and size of its text and icons, as rel-button's `size`: `small` = 32px, `medium` = 40px (default), `large` = 48px. The menu rows take the same size. Reflected. |
|
|
68
|
+
| `disabled` | `disabled` | `boolean` | `false` | Dims both segments to rel-button's disabled look (the divider keeps its colour), removes them from the Tab order and keeps the menu closed. Reflected. |
|
|
69
|
+
| `loading` | `loading` | `boolean` | `false` | The main action shows only rel-button's spinner, at its minimum width; its text stays its accessible name (visually hidden) and it is `aria-busy`. Its clicks are blocked and the chevron is disabled, so nothing else starts mid-request; an open menu closes. Reflected. |
|
|
70
|
+
| `iconOnly` | `icon-only` | `boolean` | `false` | The main action is a square of the button's height (32 / 40 / 48), as rel-button's `icon-only`: give it a single icon (`icon`, or a slotted `rel-icon`) and set `aria-label`. Reflected. |
|
|
71
|
+
| `ariaLabel` | `aria-label` | `string \| null` | `null` | Accessible name of the main action, forwarded to its native `<button>`. Required with `icon-only`, where the main action has no visible text (a console warning names split buttons without one). |
|
|
72
|
+
| `menuLabel` | `menu-label` | `string` | `"More options"` | Accessible name of the chevron button (attribute `menu-label`); it has no visible text. |
|
|
73
|
+
| `icon` | `icon` | `string` | `""` | `rel-icon` name drawn before the main action's text (16 / 18 / 20px by size). |
|
|
74
|
+
| `items` | `items` | `SplitButtonItem[]` | `[]` | The menu entries, each `{ value, label, icon?, disabled? }`. Set as a property (or a JSON array attribute). |
|
|
75
|
+
| `open` | `open` | `boolean` | `false` | Whether the menu is open. Updated by the component (and announced with `rel-open-change`); set it to open or close the menu from code. Reflected. |
|
|
76
|
+
|
|
77
|
+
## Events
|
|
78
|
+
|
|
79
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
80
|
+
| --- | --- | --- | --- |
|
|
81
|
+
| `rel-open-change` | `{ open }` | bubbles / composed | The menu opened or closed (chevron, keyboard, Escape, an outside click, Tab away, or a choice). Detail: `{ open: boolean }`. |
|
|
82
|
+
| `rel-select` | `{ value, item }` | bubbles / composed | A menu entry was chosen with a click, Enter or Space; the menu has closed and focus is back on the chevron. Detail: `{ value: string, item: SplitButtonItem }`. |
|
|
83
|
+
|
|
84
|
+
## Slots
|
|
85
|
+
|
|
86
|
+
| Slot | Description |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| (default) | The main action's content (text, or a `rel-icon` and text). Falls back to `label`. |
|
|
89
|
+
|
|
90
|
+
## CSS Parts
|
|
91
|
+
|
|
92
|
+
| Part | Description |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `main` | The main action's native `<button>`. |
|
|
95
|
+
| `indicator` | The loading spinner on the main action, rendered only while `loading` is set. |
|
|
96
|
+
| `toggle` | The chevron's native `<button>` (`aria-haspopup="menu"`, `aria-expanded`, named by `menu-label`). |
|
|
97
|
+
|
|
98
|
+
## Tokens / CSS Variables
|
|
99
|
+
|
|
100
|
+
### Component hooks
|
|
101
|
+
|
|
102
|
+
Set these on the host (or an ancestor) to customise the element without touching design tokens.
|
|
103
|
+
|
|
104
|
+
| Custom property | Default | Description |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| `--rel-split-button-menu-width` | `max-content` | Width of the menu (default `max-content`). The menu is never narrower than the split button. |
|
|
107
|
+
|
|
108
|
+
<!-- readme-gen:end -->
|
|
109
|
+
|
|
110
|
+
## Accessibility
|
|
111
|
+
|
|
112
|
+
- The main action is a native `<button>` named by its content. The chevron is a native `<button>` with `aria-haspopup="menu"`, `aria-expanded` and the accessible name from `menu-label` (default "More options").
|
|
113
|
+
- The menu is a `rel-menu` (`role="menu"`); its rows are `role="menuitem"`, and a disabled entry has `aria-disabled="true"`. Item icons are hidden from assistive technology.
|
|
114
|
+
- `loading` shows only the spinner, sets `aria-busy="true"` on the main action and keeps its text as its accessible name (visually hidden). The chevron is disabled while it loads, so it leaves the Tab order.
|
|
115
|
+
- With `icon-only`, the main action has no visible text: set `aria-label`, which is forwarded to its `<button>`. The element logs a console warning without one (a `label` is not drawn and does not name it).
|
|
116
|
+
- Each segment shows rel-button's focus ring. A mouse open shows no ring in the menu, and none on the chevron when the menu closes; the first arrow key brings the row ring back.
|
|
117
|
+
|
|
118
|
+
### Keyboard
|
|
119
|
+
|
|
120
|
+
| Key | Action |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| Tab / Shift+Tab | Two Tab stops: the main action, then the chevron |
|
|
123
|
+
| Enter / Space (main action) | Runs the main action (`click`) |
|
|
124
|
+
| Enter / Space / Down (chevron) | Opens the menu on its first entry |
|
|
125
|
+
| Up (chevron) | Opens the menu on its last entry |
|
|
126
|
+
| Down / Up, Home / End (menu) | Moves through the entries |
|
|
127
|
+
| Enter / Space (menu) | Chooses the entry: fires `rel-select`, closes the menu and returns focus to the chevron |
|
|
128
|
+
| Escape (menu) | Closes the menu and returns focus to the chevron |
|
|
129
|
+
| Tab (menu) | Closes the menu and moves focus on |
|