@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,117 +1,122 @@
1
- # rel-switch
2
-
3
- `<rel-switch>` implements the Figma **Switch** component (5917:1174, Type=Line): a 44×20 toggle with a thin 10px track and a 20px handle that slides 20px, with hover, focused, pressed and disabled states from the Figma State axis. It wraps a native checkbox with `role="switch"`, so keyboard and screen-reader behaviour are native. Use it for settings that take effect immediately (notifications on/off, dark mode); for choices that are collected and submitted with a form use `<rel-checkbox>`.
4
-
5
- ## Usage
6
-
7
- ```html
8
- <!-- Basic -->
9
- <rel-switch field-aria-label="Email notifications"></rel-switch>
10
-
11
- <!-- On by default -->
12
- <rel-switch checked field-aria-label="Dark mode"></rel-switch>
13
-
14
- <!-- Disabled, off and on -->
15
- <rel-switch disabled field-aria-label="Locked setting"></rel-switch>
16
- <rel-switch checked disabled field-aria-label="Locked setting"></rel-switch>
17
-
18
- <!-- One handler for several switches: `value` is echoed in the event detail -->
19
- <rel-switch value="marketing" field-aria-label="Marketing emails"></rel-switch>
20
- <rel-switch value="product" field-aria-label="Product updates"></rel-switch>
21
- <script>
22
- document.addEventListener('rel-change', (e) => {
23
- if (e.target.tagName !== 'REL-SWITCH') return;
24
- console.log(e.detail.value, e.detail.checked); // "marketing", true
25
- });
26
- </script>
27
-
28
- <!-- Programmatic control (no event is fired) -->
29
- <rel-switch id="wifi" field-aria-label="Wi-Fi"></rel-switch>
30
- <script>
31
- const wifi = document.getElementById('wifi');
32
- wifi.checked = true;
33
- </script>
34
- ```
35
-
36
- <!-- readme-gen:start -->
37
-
38
- <!-- Generated from rel-switch.ts — do not edit; run readme-generate.mjs -->
39
-
40
- ## API
41
-
42
- ### Attributes / Properties
43
-
44
- | Property | Attribute | Type | Default | Description |
45
- | --- | --- | --- | --- | --- |
46
- | `checked` | `checked` | `boolean` | `false` | Whether the switch is on. Set it to control the state programmatically; user toggles update it and fire `rel-change`. |
47
- | `type` | `type` | `"line" \| "pill"` | `"line"` | Shape (Figma "Type"): `"line"` (default) is the 44x20 control with a thin 40x10 rail and the handle riding on it; `"pill"` is the 44x24 filled track with the handle inside it. NOTE: Figma's own default is Pill. We default to `line` deliberately — flipping it would restyle every existing switch — so this is a recorded divergence from the design default, not an oversight. Reflected. |
48
- | `disabled` | `disabled` | `boolean` | `false` | Disables interaction and swaps in the dulled rail / handle fills; the handle shadow is removed. |
49
- | `value` | `value` | `string` | `""` | Arbitrary string echoed in the `rel-change` event detail — useful when one handler serves several switches. |
50
- | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the native input. Without it the switch has no label of its own, so pair it with a visible `<label>` or set this. |
51
- | `label` | `label` | `string` | `undefined` | Visible text beside the control. Clicking it toggles the switch, and it becomes the accessible name — use `fieldAriaLabel` instead when the switch has no visible text. For rich content (a bold word, an icon) slot it in the default slot rather than setting this. |
52
- | `labelPlacement` | `label-placement` | `"end" \| "start"` | `"end"` | Which side the label sits on: `end` (default) puts it after the control, `start` before it. Note this is a PHYSICAL side, not a writing-direction one, matching every other placement prop in the library. Reflected. |
53
- | `size` | `size` | `"small" \| "medium" \| "large" \| "sm" \| "md" \| "lg"` | `"medium"` | Control scale: `small`, `medium` (default) or `large`. `sm` / `md` / `lg` are alternative spellings and stay supported — normalised to the full words, not deprecated. Figma's Switch has axes Type / State / Enabled only, with no Size, so this ramp is ours. `medium` is exactly the control that shipped before it existed, so an existing switch is unchanged. It does NOT respond to viewport width. Picking a size per breakpoint is the consuming application's decision — a control that silently resized itself at some width would be undocumentable behaviour, and the breakpoint that matters belongs to the layout around it, not to the switch. Reflected. |
54
-
55
- ## Events
56
-
57
- | Event | Detail | Bubbles / composed | Description |
58
- | --- | --- | --- | --- |
59
- | `rel-change` | `{ checked: this.checked, value: this.value, }` | bubbles / composed | Fired when the user toggles the switch (not on programmatic `checked` changes). Detail: `{ checked: boolean, value: string }`. |
60
-
61
- ## Slots
62
-
63
- | Slot | Description |
64
- | --- | --- |
65
- | (default) | Rich label content beside the control, as an alternative to the `label` property. Clicking it toggles the switch. |
66
-
67
- ## CSS Parts
68
-
69
- | Part | Description |
70
- | --- | --- |
71
- | `root` | The `<label>` holding the control and its optional text; carries the `label-placement` order |
72
- | `base` | The control box around the hidden input and the track |
73
- | `track` | The thin rail; the handle is its `::before` pseudo-element |
74
- | `label` | The text beside the control; not rendered when there is neither a `label` nor slotted content |
75
-
76
- ## Tokens / CSS Variables
77
-
78
- ### Component hooks
79
-
80
- Set these on the host (or an ancestor) to customise the element without touching design tokens.
81
-
82
- | Custom property | Default | Description |
83
- | --- | --- | --- |
84
- | `--rel-switch-disabled` | `var(--switch-disabled)` | Handle colour while disabled; default `var(--rel-bg-neutral-elevated-1)` |
85
- | `--rel-switch-knob-off` | `var(--switch-knob-off)` | Handle colour when unchecked; default `var(--rel-text-static-light)` |
86
- | `--rel-switch-knob-on` | `var(--switch-knob-on)` | Handle colour when checked; default `var(--rel-bg-neutral-inverse-2)` |
87
- | `--rel-switch-thumb-size` | `var(--_rel-sw-thumb)` | Handle diameter; defaults to the `size` ramp (16 / 20 / 24px), and the handle always travels its own width minus the 2px inset on each side |
88
- | `--rel-switch-track` | `var(--switch-track)` | Rail colour; default `var(--rel-bg-neutral-elevated-2)` |
89
- | `--rel-switch-track-height` | `var(--_rel-sw-h)` | Overall control height; defaults to the `size` ramp — 16 / 20 / 24px for `type="line"`, 20 / 24 / 28px for `type="pill"` |
90
- | `--rel-switch-track-width` | `var(--_rel-sw-w)` | Overall control width; defaults to the `size` ramp (36 / 44 / 52px) |
91
- | `--switch-halo` | `var(--rel-action-overlay-hover-strong)` | — |
92
-
93
- <!-- readme-gen:end -->
94
-
95
- ## Accessibility
96
-
97
- - Renders a native `<input type="checkbox" role="switch">` with `aria-checked` mirroring `checked`; the input is visually hidden (opacity 0, zero size) inside a `<label part="base">`, so clicking anywhere on the control toggles it.
98
- - `field-aria-label` becomes the input's `aria-label`. The input lives in the shadow root, so an external `<label for>` cannot reference it — set `field-aria-label` for the accessible name and place any visible text beside the switch.
99
- - Focus: the wrapper shows a 1.5px focus outline whenever the input is focused (mouse or keyboard).
100
- - `disabled` disables the native input (removed from the tab order), dims the control to 50% and drops the handle shadow.
101
- - `prefers-reduced-motion: reduce` removes the track and handle transitions.
102
-
103
- | Key | Action |
104
- | --- | --- |
105
- | `Space` | Toggles the switch (native checkbox behaviour). |
106
- | `Tab` / `Shift+Tab` | Moves focus to / from the switch. |
107
-
108
- ## Notes / Edge Cases
109
-
110
- - `rel-change` fires for user toggles only; setting `checked` from JavaScript updates the visuals but emits nothing.
111
- - Geometry follows the `size` ramp, derived from the Figma Line switch at `medium`: 44×20 control, 40×10 track inset 2px, 20px handle travelling 20px. `small` is 36×16 and `large` 52×24, holding the same invariants (handle = control height, width = 2× height + 4, rail = height ÷ 2, travel = width − 4 − handle). `type="pill"` shares the width, handle and travel but is 4px taller at every size — 20 / 24 / 28 — because its height is the handle plus its 2px inset, where Line's height *is* the handle. Changing `--rel-switch-track-width` widens the control without moving the "on" position.
112
- - **`size` does not respond to viewport width.** Figma has no Size axis on Switch, so the ramp is ours, and choosing a size per breakpoint is the application's decision — set it from your own media queries or container queries. A control that resized itself at some width would be behaviour a design system cannot document, and the breakpoint that matters belongs to the layout around the switch, not to the switch.
113
- - A `label` (or slotted content) becomes the switch's accessible name and is clickable, because the root element is the `<label>` that owns the input. Use `field-aria-label` instead when there is no visible text; when both are set, `label` wins.
114
- - Figma's default Type=Pill switch (44×24 filled track with the handle inside) is not implemented.
115
- - Hover tints the track with the action overlay and raises the handle shadow; pressed shows a 28px overlay disc behind the handle and squashes it to 20×16.
116
- - Legacy hook aliases still honoured: `--switch-track`, `--switch-knob-on`, `--switch-knob-off` and `--switch-disabled` are read as fallbacks of the `--rel-switch-*` hooks. The old `--switch-halo` name was never read by any rule and is not a hook.
117
- - `registerOnChange`, `registerOnTouched` and `writeValue` exist for the Angular `ControlValueAccessor` wrapper and are not public API.
1
+ # rel-switch
2
+
3
+ `<rel-switch>` implements the Figma **Switch** component set (9059:11244): Type Line (default; at medium a 44×20 toggle with a thin 10px track and a 20px handle that slides 20px) or Pill (a 44×24 filled track), three sizes, an optional label at either end, and the hover, pressed, focused and disabled states from the Figma State axis. It wraps a native checkbox with `role="switch"`, so keyboard and screen-reader behaviour are native. Use it for settings that take effect immediately (notifications on/off, dark mode); for choices that are collected and submitted with a form use `<rel-checkbox>`.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Basic -->
9
+ <rel-switch field-aria-label="Email notifications"></rel-switch>
10
+
11
+ <!-- On by default -->
12
+ <rel-switch checked field-aria-label="Dark mode"></rel-switch>
13
+
14
+ <!-- Disabled, off and on -->
15
+ <rel-switch disabled field-aria-label="Locked setting"></rel-switch>
16
+ <rel-switch checked disabled field-aria-label="Locked setting"></rel-switch>
17
+
18
+ <!-- One handler for several switches: `value` is echoed in the event detail -->
19
+ <rel-switch value="marketing" field-aria-label="Marketing emails"></rel-switch>
20
+ <rel-switch value="product" field-aria-label="Product updates"></rel-switch>
21
+ <script>
22
+ document.addEventListener('rel-change', (e) => {
23
+ if (e.target.tagName !== 'REL-SWITCH') return;
24
+ console.log(e.detail.value, e.detail.checked); // "marketing", true
25
+ });
26
+ </script>
27
+
28
+ <!-- Programmatic control (no event is fired) -->
29
+ <rel-switch id="wifi" field-aria-label="Wi-Fi"></rel-switch>
30
+ <script>
31
+ const wifi = document.getElementById('wifi');
32
+ wifi.checked = true;
33
+ </script>
34
+ ```
35
+
36
+ <!-- readme-gen:start -->
37
+
38
+ <!-- Generated from rel-switch.ts — do not edit; run readme-generate.mjs -->
39
+
40
+ ## API
41
+
42
+ ### Attributes / Properties
43
+
44
+ | Property | Attribute | Type | Default | Description |
45
+ | --- | --- | --- | --- | --- |
46
+ | `checked` | `checked` | `boolean` | `false` | Whether the switch is on. Set it to control the state programmatically; user toggles update it and fire `rel-change`. |
47
+ | `type` | `type` | `"line" \| "pill"` | `"line"` | Shape (Figma "Type"): `"line"` (default) is the 44x20 control with a thin 40x10 rail and the handle riding on it; `"pill"` is the 44x24 filled track with the handle inside it. Pressing squashes the handle; only `line` also shows a pressed disc behind it. Reflected. |
48
+ | `disabled` | `disabled` | `boolean` | `false` | Disables interaction and swaps in the dulled rail / handle fills (for both types, checked or not) and the disabled label colour; the handle shadow is removed. An ancestor `<fieldset disabled>` disables it the same way, without changing this property. |
49
+ | `value` | `value` | `string` | `""` | Arbitrary string echoed in the `rel-change` event detail — useful when one handler serves several switches. |
50
+ | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the native input when the switch has no visible text. Prefer `label`, slotted text or an outer `<label>` (wrapping the switch, or `for=`), which are visible and clickable. |
51
+ | `label` | `label` | `string` | `undefined` | Visible text beside the control. Clicking it toggles the switch, and it becomes the accessible name — use `fieldAriaLabel` instead when the switch has no visible text. For rich content (a bold word, an icon) slot it in the default slot rather than setting this. |
52
+ | `labelPlacement` | `label-placement` | `"end" \| "start"` | `"end"` | Which side the label sits on: `end` (default) puts it after the control, `start` before it. Note this is a PHYSICAL side, not a writing-direction one, matching every other placement prop in the library. Reflected. |
53
+ | `size` | `size` | `"small" \| "medium" \| "large" \| "sm" \| "md" \| "lg"` | `"medium"` | Control scale: `small`, `medium` (default) or `large`. `sm` / `md` / `lg` are alternative spellings and stay supported — normalised to the full words, not deprecated. Matches Figma's Size axis: controls 36 / 44 / 52px wide, labels body-sm / body-md / body-lg (12 / 14 / 16px). The default stays `medium` (Figma's own default is Large). It does NOT respond to viewport width. Picking a size per breakpoint is the consuming application's decision — a control that silently resized itself at some width would be undocumentable behaviour, and the breakpoint that matters belongs to the layout around it, not to the switch. Reflected. |
54
+
55
+ ## Events
56
+
57
+ | Event | Detail | Bubbles / composed | Description |
58
+ | --- | --- | --- | --- |
59
+ | `rel-change` | `{ checked: this.checked, value: this.value, }` | bubbles / composed | Fired when the user toggles the switch (not on programmatic `checked` changes). Detail: `{ checked: boolean, value: string }`. |
60
+
61
+ ## Slots
62
+
63
+ | Slot | Description |
64
+ | --- | --- |
65
+ | (default) | Rich label content beside the control, as an alternative to the `label` property. Clicking it toggles the switch. |
66
+
67
+ ## CSS Parts
68
+
69
+ | Part | Description |
70
+ | --- | --- |
71
+ | `root` | The `<label>` holding the control and its optional text; carries the `label-placement` order and the keyboard focus ring |
72
+ | `base` | The control box around the hidden input and the track |
73
+ | `track` | The thin rail; the handle is its `::before` pseudo-element |
74
+ | `label` | The text beside the control (body-sm / body-md / body-lg by `size`; `--rel-text-disabled` while disabled); not rendered when there is neither a `label` nor slotted content |
75
+
76
+ ## Tokens / CSS Variables
77
+
78
+ ### Component hooks
79
+
80
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
81
+
82
+ | Custom property | Default | Description |
83
+ | --- | --- | --- |
84
+ | `--rel-switch-disabled` | `var(--switch-disabled)` | Handle colour while disabled; default `var(--rel-bg-neutral-elevated-1)` |
85
+ | `--rel-switch-knob-off` | `var(--switch-knob-off)` | Handle colour when unchecked; default `var(--rel-text-static-light)` |
86
+ | `--rel-switch-knob-on` | `var(--switch-knob-on)` | Handle colour when checked; default `var(--rel-bg-neutral-inverse-2)` |
87
+ | `--rel-switch-thumb-size` | `var(--_rel-sw-thumb)` | Handle diameter; defaults to the `size` ramp (16 / 20 / 24px), and the handle always travels its own width minus the 2px inset on each side |
88
+ | `--rel-switch-track` | `var(--switch-track)` | Rail colour; default `var(--rel-bg-neutral-elevated-2)` |
89
+ | `--rel-switch-track-height` | `var(--_rel-sw-h)` | Overall control height; defaults to the `size` ramp — 16 / 20 / 24px for `type="line"`, 20 / 24 / 28px for `type="pill"` |
90
+ | `--rel-switch-track-width` | `var(--_rel-sw-w)` | Overall control width; defaults to the `size` ramp (36 / 44 / 52px) |
91
+ | `--switch-halo` | `var(--rel-action-overlay-hover-strong)` | — |
92
+
93
+ <!-- readme-gen:end -->
94
+
95
+ ## Accessibility
96
+
97
+ - Renders a native `<input type="checkbox" role="switch">` with `aria-checked` mirroring `checked`; the input is visually hidden (opacity 0, zero size) inside the `<label part="root">` that also holds the label text, so clicking anywhere on the control or its text toggles it.
98
+ - `field-aria-label` becomes the input's `aria-label`. Use it only when there is no visible text; visible text in `label` or the default slot is clickable and becomes the accessible name.
99
+ - An outer `<label>` works too, wrapped around the switch (`<label><rel-switch></rel-switch> Wi-Fi</label>`) or pointing at it (`<label for="wifi">Wi-Fi</label><rel-switch id="wifi">`). The element is form-associated, so clicking the label's text toggles the switch (once, with one `rel-change`); a disabled switch ignores it. The input lives in the shadow root, where `aria-labelledby` cannot reach the label, so the label's text is copied into the input's `aria-label`. That happens only when the switch has no name of its own: `label`, `field-aria-label` and slotted text each win over an outer label. The copy follows edits to the label's text.
100
+ - Focus: keyboard focus (`:focus-visible`) draws one square 1.5px `--rel-border-focus` outline around the whole component, control and label together (the same treatment as `rel-checkbox` and `rel-radio`). A pointer click shows no ring.
101
+ - `disabled` disables the native input (removed from the tab order), swaps in the dulled rail and handle fills, drops the handle shadow and colours the label `--rel-text-disabled`.
102
+ - Forced colors (Windows High Contrast): the rail and handle are redrawn from system colours (a CanvasText outline, the handle filled Highlight when on, GrayText while disabled), and the focus ring stays an outline.
103
+ - `prefers-reduced-motion: reduce` removes the track and handle transitions.
104
+
105
+ | Key | Action |
106
+ | --- | --- |
107
+ | `Space` | Toggles the switch (native checkbox behaviour). |
108
+ | `Tab` / `Shift+Tab` | Moves focus to / from the switch. |
109
+
110
+ ## Notes / Edge Cases
111
+
112
+ - `rel-change` fires for user toggles only; setting `checked` from JavaScript updates the visuals but emits nothing.
113
+ - Geometry follows the `size` ramp, derived from the Figma Line switch at `medium`: 44×20 control, 40×10 track inset 2px, 20px handle travelling 20px. `small` is 36×16 and `large` 52×24, holding the same invariants (handle = control height, width = 2× height + 4, rail = height ÷ 2, travel = width − 4 − handle). `type="pill"` shares the width, handle and travel but is 4px taller at every size — 20 / 24 / 28 — because its height is the handle plus its 2px inset, where Line's height *is* the handle. Changing `--rel-switch-track-width` widens the control without moving the "on" position.
114
+ - The label type follows the size: body-sm / body-md / body-lg (12 / 14 / 16px) for small / medium / large.
115
+ - **`size` does not respond to viewport width.** It follows Figma's Size axis, and choosing a size per breakpoint is the application's decision — set it from your own media queries or container queries. A control that resized itself at some width would be behaviour a design system cannot document, and the breakpoint that matters belongs to the layout around the switch, not to the switch.
116
+ - A `label` (or slotted content) becomes the switch's accessible name and is clickable, because the root element is the `<label>` that owns the input. Use `field-aria-label` instead when there is no visible text; when both are set, `label` wins.
117
+ - Hover and pressed cover the whole component, label included. Hover tints the track with the action overlay and raises the handle shadow. Pressed (pointer down, or Space held) squashes the handle by 4px on Line (16×12 / 20×16 / 24×20) over an overlay disc 8px wider than the handle, and to (handle + 1) × (handle − 2) on Pill, with no disc; an unchecked rail turns `--rel-bg-neutral-elevated-1` while pressed.
118
+ - Legacy hook aliases still honoured: `--switch-track`, `--switch-knob-on`, `--switch-knob-off` and `--switch-disabled` are read as fallbacks of the `--rel-switch-*` hooks. The old `--switch-halo` name was never read by any rule and is not a hook.
119
+ - `registerOnChange`, `registerOnTouched` and `writeValue` exist for the Angular `ControlValueAccessor` wrapper and are not public API.
120
+ - The element is form-associated (so an outer `<label>` can find it) but sets no form value: it is still NOT submitted with a surrounding `<form>`, and form reset does not touch it. It does now appear in `form.elements`. Read `checked` or listen to `rel-change`.
121
+ - Inside a `<fieldset disabled>` the switch behaves disabled (input disabled, dulled fills, no toggling) without its `disabled` property changing.
122
+ - `el.click()` from script now toggles the switch, like a native checkbox; it used to do nothing.