@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,147 +1,159 @@
1
- # rel-checkbox
2
-
3
- A tri-state checkbox implementing the Figma "Checkbox" sheet: a hidden native `<input type="checkbox">` behind a custom box, with a label, an optional label-prefix icon and optional supporting text. It exposes the sheet's vocabulary verbatim — `size` (small / medium / large / extra-large), `density` (compact / comfortable) and `alignment` (leading / trailing) — plus `state` for error and disabled styling. Use it for independent yes/no choices and for "select all" parents (via `status="indeterminate"`); for a single choice among several options use `rel-radio`, and for an immediate on/off setting use `rel-switch`.
4
-
5
- ## Usage
6
-
7
- ```html
8
- <!-- Basic -->
9
- <rel-checkbox label="Accept terms"></rel-checkbox>
10
-
11
- <!-- Supporting text, compact density (default: text on its own line, indented past the box) -->
12
- <rel-checkbox
13
- label="Subscribe to newsletter"
14
- supportingtext="We'll send you weekly updates"
15
- status="unchecked"
16
- state="default">
17
- </rel-checkbox>
18
-
19
- <!-- Comfortable density: label + supporting text stack beside the box -->
20
- <rel-checkbox
21
- density="comfortable"
22
- label="Notify the broker"
23
- supportingtext="Sends an email when the POD is uploaded">
24
- </rel-checkbox>
25
-
26
- <!-- Trailing alignment: box at the far edge of the row (settings-row style).
27
- Trailing always renders comfortable density — compact has no trailing layout. -->
28
- <rel-checkbox
29
- alignment="trailing"
30
- label="Email notifications"
31
- supportingtext="Weekly summary of load activity">
32
- </rel-checkbox>
33
-
34
- <!-- Sizes (medium is the default) -->
35
- <rel-checkbox size="small" label="Include archived"></rel-checkbox>
36
- <rel-checkbox size="large" label="I agree to the terms"></rel-checkbox>
37
-
38
- <!-- Label prefix icon -->
39
- <rel-checkbox icon="truck" label="Truckload only"></rel-checkbox>
40
-
41
- <!-- Error and disabled states -->
42
- <rel-checkbox state="error" label="Required consent"></rel-checkbox>
43
- <rel-checkbox state="disabled" status="checked" label="Locked by admin"></rel-checkbox>
44
-
45
- <!-- Indeterminate (programmatic-only; a user toggle resolves to checked/unchecked) -->
46
- <rel-checkbox id="select-all" label="Select all" status="indeterminate"></rel-checkbox>
47
- <script>
48
- document.getElementById('select-all').addEventListener('rel-change', (e) => {
49
- console.log(e.detail.checked, e.detail.value);
50
- });
51
- </script>
52
- ```
53
-
54
- <!-- readme-gen:start -->
55
-
56
- <!-- Generated from rel-checkbox.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` | `"Label"` | Label text rendered next to the box. |
65
- | `icon` | `icon` | `string` | `""` | rel-icon name rendered between the checkbox and the label (label prefix icon); scales with `size`. Unset renders no icon and reserves no space. |
66
- | `supportingtext` | `supportingtext` | `string` | `""` | Supporting text under or beside the label; where it renders depends on `density`. |
67
- | `state` | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual and interaction state (Figma State): `"error"` swaps in the danger colours, `"disabled"` blocks input and dims the whole control to 0.4 opacity (colours unchanged, as Figma specifies). |
68
- | `status` | `status` | `"unchecked" \| "checked" \| "indeterminate"` | `"unchecked"` | Check state. `"indeterminate"` is programmatic-only — a user toggle always resolves to checked or unchecked. |
69
- | `value` | `value` | `string` | `""` | Value reported in the `rel-change` event detail (it is not submitted with a form). |
70
- | `size` | `size` | `"small" \| "medium" \| "large" \| "extra-large"` | `"medium"` | Control scale (Figma Size), on Figma's four-step ramp of control frames: `"small"` 16px / body-sm, `"medium"` (default) 18px / body-md, `"large"` 20px / body-lg, `"extra-large"` 24px / body-xl. Supporting text sits one body step below the label at every size (body-xs / sm / md / lg, i.e. 10 / 12 / 14 / 16px). The drawn square is inset to 80% of the frame, so the frame is the layout footprint (what the row gap and the compact indent measure from) rather than the visible square. Reflected. |
71
- | `density` | `density` | `"compact" \| "comfortable"` | `"compact"` | Supporting-text layout (Figma Density). `"compact"` (default) puts the supporting text on its own line under the row, indented past the box; `"comfortable"` stacks label + supporting text beside the box. Reflected. |
72
- | `alignment` | `alignment` | `"leading" \| "trailing"` | `"leading"` | Box position (Figma Alignment). `"leading"` (default) renders the box before the label; `"trailing"` pushes it to the far edge of the row. Trailing has no compact layout in the spec, so it always renders with comfortable density. Reflected. |
73
- | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the native checkbox, for when the visible `label` is absent or not a usable name on its own — a checkbox in a table row, or one whose meaning comes from its column header. Normally unnecessary: the input is wrapped in the `<label>` that renders `label`, so the visible text already names it natively. Setting this puts an `aria-label` on the input, which OVERRIDES that wrapping label — so set it only when the visible text is the wrong name, not to repeat it. Left unset the attribute is not emitted at all. |
74
-
75
- ### Public fields / accessors
76
-
77
- | Name | Type | Description |
78
- | --- | --- | --- |
79
- | `checked` | `boolean` | Boolean view of `status`: `true` when `status === "checked"`; setting it writes `"checked"` / `"unchecked"`. |
80
-
81
- ## Events
82
-
83
- | Event | Detail | Bubbles / composed | Description |
84
- | --- | --- | --- | --- |
85
- | `rel-change` | `{ checked: this.status === "checked", value: this.value, }` | bubbles / composed | Fired after a user toggle. Detail: `{ checked: boolean, value: string }`. |
86
-
87
- ## Slots
88
-
89
- | Slot | Description |
90
- | --- | --- |
91
- | — | This element has no slots. |
92
-
93
- ## CSS Parts
94
-
95
- | Part | Description |
96
- | --- | --- |
97
- | `base` | The outer wrapper that carries the `state` / `status` classes |
98
- | `label` | The visible label text |
99
- | `helper` | The supporting text (rendered beside the box in comfortable density, under the row in compact) |
100
-
101
- <!-- readme-gen:end -->
102
-
103
- ## Accessibility
104
-
105
- - A visually hidden native `<input type="checkbox">` carries the semantics; the custom box is decorative. The input is wrapped in a `<label>`, so clicking anywhere on the row (label, icon or box — the whole row in trailing alignment) toggles it.
106
- - `status="indeterminate"` sets the native `indeterminate` flag and `aria-checked="mixed"` on the input, so screen readers announce the mixed state.
107
- - `state="disabled"` sets the native `disabled` attribute (the input leaves the tab order) and blocks pointer events on the whole element.
108
- - Focus: `:focus-visible` on the hidden input draws a 2px `--rel-border-focus` outline with a 2px offset around the box.
109
- - No live-region announcements are made; the native checkbox reports its own state changes.
110
-
111
- | Key | Action |
112
- | --- | --- |
113
- | `Tab` / `Shift+Tab` | Move focus to / from the checkbox |
114
- | `Space` | Toggle between checked and unchecked (native behaviour; indeterminate resolves to checked) |
115
-
116
- ## Notes / Edge Cases
117
-
118
- - User toggling is binary: indeterminate is never entered by interaction. Set `status="indeterminate"` programmatically (e.g. a Select-All parent driven by app state).
119
- - `checked` is a convenience accessor over `status` (used by the Angular ControlValueAccessor wrapper); reading it is `status === "checked"`, writing it sets `"checked"` / `"unchecked"`.
120
- - `alignment="trailing"` with `density="compact"` is "Not available" in the Figma sheet: the element renders comfortable density and logs `[rel-checkbox] density="compact" has no trailing layout; rendering comfortable density.` once per change.
121
- - Comfortable density with no supporting text is visually identical to compact.
122
- - The host is `display: block`, so a trailing checkbox stretches to its container width; constrain the parent to control row width.
123
- - `value` is only reported in the `rel-change` detail — the element does not participate in native form submission.
124
- - The hidden native input is absolutely positioned against the `.row` containing block; keep `position: relative` on `.row` (Tab-scroll page-jump fix, shared with rel-radio).
125
- - Control frames are 16 / 18 / 20 / 24px for small / medium / large / extra-large, matching Figma. The frame is the layout footprint — the row gap and the compact indent measure from it — while the drawn square is inset to 80% of the frame (12.8 / 14.4 / 16 / 19.2px), as Figma draws it.
126
- - The square's 2px border weight is **not** verified against Figma: the control is flattened artwork (a filled vector rather than a frame with a stroke), so the sheet gives the square's outer size but says nothing about its stroke. Carried forward from the previous implementation.
127
-
128
- ### Layout matrix (mirrors the Figma sheet)
129
-
130
- | Size | Density | Leading | Trailing |
131
- | --- | --- | --- | --- |
132
- | M | Comfortable | yes | yes |
133
- | M | Compact | yes (default) | renders comfortable |
134
- | S | Comfortable | yes | yes |
135
- | S | Compact | yes | renders comfortable |
136
- | L | Comfortable | yes | yes |
137
- | L | Compact | yes | renders comfortable |
138
- | XL | Comfortable | yes | yes |
139
- | XL | Compact | yes | renders comfortable |
140
-
141
- ### Recipes (intentionally not component props)
142
-
143
- - **Selectable list row**: `alignment="trailing"` checkbox inside a padded, hover-highlighted container.
144
- - **Select All / nested group**: parent checkbox with `status="indeterminate"` wired to children in app state.
145
- - **Selectable card**: `rel-card` wrapping a checkbox; toggle a selected border on `rel-change`.
146
-
147
- See the Storybook Checkbox stories for working recipe markup.
1
+ # rel-checkbox
2
+
3
+ A tri-state checkbox implementing the Figma "Checkbox" sheet: a hidden native `<input type="checkbox">` behind a custom box, with a label, an optional label-prefix icon and optional supporting text. It exposes the sheet's vocabulary verbatim — `size` (small / medium / large / extra-large), `density` (compact / comfortable) and `alignment` (leading / trailing) — plus `state` for error and disabled styling. Use it for independent yes/no choices and for "select all" parents (via `status="indeterminate"`); for a single choice among several options use `rel-radio`, and for an immediate on/off setting use `rel-switch`.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Basic -->
9
+ <rel-checkbox label="Accept terms"></rel-checkbox>
10
+
11
+ <!-- Supporting text, compact density (default: text on its own line, indented past the box) -->
12
+ <rel-checkbox
13
+ label="Subscribe to newsletter"
14
+ supporting-text="We'll send you weekly updates"
15
+ status="unchecked"
16
+ state="default">
17
+ </rel-checkbox>
18
+
19
+ <!-- Comfortable density: label + supporting text stack beside the box -->
20
+ <rel-checkbox
21
+ density="comfortable"
22
+ label="Notify the broker"
23
+ supporting-text="Sends an email when the POD is uploaded">
24
+ </rel-checkbox>
25
+
26
+ <!-- Trailing alignment: box at the far edge of the row (settings-row style).
27
+ Trailing always renders comfortable density — compact has no trailing layout. -->
28
+ <rel-checkbox
29
+ alignment="trailing"
30
+ label="Email notifications"
31
+ supporting-text="Weekly summary of load activity">
32
+ </rel-checkbox>
33
+
34
+ <!-- Sizes (medium is the default) -->
35
+ <rel-checkbox size="small" label="Include archived"></rel-checkbox>
36
+ <rel-checkbox size="large" label="I agree to the terms"></rel-checkbox>
37
+
38
+ <!-- Label prefix icon -->
39
+ <rel-checkbox icon="truck" label="Truckload only"></rel-checkbox>
40
+
41
+ <!-- Error and disabled states -->
42
+ <rel-checkbox state="error" label="Required consent"></rel-checkbox>
43
+ <rel-checkbox state="disabled" status="checked" label="Locked by admin"></rel-checkbox>
44
+
45
+ <!-- Indeterminate (programmatic-only; a user toggle resolves to checked/unchecked) -->
46
+ <rel-checkbox id="select-all" label="Select all" status="indeterminate"></rel-checkbox>
47
+ <script>
48
+ document.getElementById('select-all').addEventListener('rel-change', (e) => {
49
+ console.log(e.detail.checked, e.detail.value);
50
+ });
51
+ </script>
52
+ ```
53
+
54
+ ### Deprecated aliases
55
+
56
+ ```html
57
+ <!-- supportingtext → supporting-text (since 1.5.0; still works, logs a one-time console notice, removed in 3.0) -->
58
+ <rel-checkbox label="Old spelling" supportingtext="Helper line"></rel-checkbox>
59
+ <rel-checkbox label="Canonical" supporting-text="Helper line"></rel-checkbox>
60
+ ```
61
+
62
+ <!-- readme-gen:start -->
63
+
64
+ <!-- Generated from rel-checkbox.ts — do not edit; run readme-generate.mjs -->
65
+
66
+ ## API
67
+
68
+ ### Attributes / Properties
69
+
70
+ | Property | Attribute | Type | Default | Description |
71
+ | --- | --- | --- | --- | --- |
72
+ | `label` | `label` | `string` | `"Label"` | Label text rendered next to the box. |
73
+ | `icon` | `icon` | `string` | `""` | rel-icon name rendered between the checkbox and the label (label prefix icon); scales with `size`. Unset renders no icon and reserves no space. |
74
+ | `supportingtext` | `supporting-text` | `string` | `""` | Supporting text under or beside the label; where it renders depends on `density`. The `supportingtext` attribute spelling is deprecated (still works; removal targeted for 3.0). |
75
+ | `state` | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual and interaction state (Figma State): `"error"` swaps in the danger colours, `"disabled"` blocks input and dims the whole control to 0.4 opacity (colours unchanged, as Figma specifies). |
76
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the checkbox exactly as `state="disabled"` does (`state` stays the documented spelling). Either one disables it, and so does an ancestor `<fieldset disabled>`; none of them changes the others. New in 1.5.0. |
77
+ | `status` | `status` | `"unchecked" \| "checked" \| "indeterminate"` | `"unchecked"` | Check state. `"indeterminate"` is programmatic-only — a user toggle always resolves to checked or unchecked. |
78
+ | `value` | `value` | `string` | `""` | Value reported in the `rel-change` event detail (it is not submitted with a form). |
79
+ | `size` | `size` | `"small" \| "medium" \| "large" \| "extra-large"` | `"medium"` | Control scale (Figma Size), on Figma's four-step ramp of control frames: `"small"` 16px / body-sm, `"medium"` (default) 18px / body-md, `"large"` 20px / body-lg, `"extra-large"` 24px / body-xl. Supporting text sits one body step below the label at every size (body-xs / sm / md / lg, i.e. 10 / 12 / 14 / 16px). The drawn square is inset to 80% of the frame, so the frame is the layout footprint (what the row gap and the compact indent measure from) rather than the visible square. Reflected. |
80
+ | `density` | `density` | `"compact" \| "comfortable"` | `"compact"` | Supporting-text layout (Figma Density). `"compact"` (default) puts the supporting text on its own line under the row, indented past the box; `"comfortable"` stacks label + supporting text beside the box. Reflected. |
81
+ | `alignment` | `alignment` | `"leading" \| "trailing"` | `"leading"` | Box position (Figma Alignment). `"leading"` (default) renders the box before the label; `"trailing"` pushes it to the far edge of the row. Trailing has no compact layout in the spec, so it always renders with comfortable density. Reflected. |
82
+ | `fieldAriaLabel` | `field-aria-label` | `string` | `undefined` | Accessible name for the native checkbox, for when the visible `label` is absent or not a usable name on its own — a checkbox in a table row, or one whose meaning comes from its column header. Normally unnecessary: the input is wrapped in the `<label>` that renders `label`, so the visible text already names it natively. Setting this puts an `aria-label` on the input, which OVERRIDES that wrapping label — so set it only when the visible text is the wrong name, not to repeat it. Left unset the attribute is not emitted at all. An outer `<label>` (wrapping the checkbox, or `for=`) names it only when neither this nor a visible `label` is set. |
83
+
84
+ ### Public fields / accessors
85
+
86
+ | Name | Type | Description |
87
+ | --- | --- | --- |
88
+ | `supportingText` | `string` | camelCase alias of `supportingtext`, matching rel-textfield and rel-select. The declared property is lowercase, so `el.supportingText = "…"`, lit `.supportingText=${…}` and Angular `[supportingText]` used to set an unused expando and render nothing. Reading or writing either name now hits the same reactive property; the attribute stays `supportingtext`. |
89
+ | `checked` | `boolean` | Boolean view of `status`: `true` when `status === "checked"`; setting it writes `"checked"` / `"unchecked"`. |
90
+
91
+ ## Events
92
+
93
+ | Event | Detail | Bubbles / composed | Description |
94
+ | --- | --- | --- | --- |
95
+ | `rel-change` | `{ checked: this.status === "checked", value: this.value, }` | bubbles / composed | Fired after a user toggle. Detail: `{ checked: boolean, value: string }`. |
96
+
97
+ ## Slots
98
+
99
+ | Slot | Description |
100
+ | --- | --- |
101
+ | — | This element has no slots. |
102
+
103
+ ## CSS Parts
104
+
105
+ | Part | Description |
106
+ | --- | --- |
107
+ | `base` | The outer wrapper that carries the `state` / `status` classes |
108
+ | `label` | The visible label text |
109
+ | `helper` | The supporting text (rendered beside the box in comfortable density, under the row in compact) |
110
+
111
+ <!-- readme-gen:end -->
112
+
113
+ ## Accessibility
114
+
115
+ - A visually hidden native `<input type="checkbox">` carries the semantics; the custom box is decorative. The input is wrapped in a `<label>`, so clicking anywhere on the row (label, icon or box — the whole row in trailing alignment) toggles it.
116
+ - An outer `<label>` works too, wrapped around the checkbox (`<label><rel-checkbox label=""></rel-checkbox> Accept terms</label>`) or pointing at it (`<label for="terms">Accept terms</label><rel-checkbox id="terms" label="">`). The element is form-associated, so clicking the label's text toggles it (once, with one `rel-change`); `state="disabled"` ignores it. Set `label=""` so the default "Label" text is not rendered. 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`, but only when the checkbox has no visible `label` and no `field-aria-label`: either one wins over an outer label. The copy follows edits to the label's text.
117
+ - `status="indeterminate"` sets the native `indeterminate` flag and `aria-checked="mixed"` on the input, so screen readers announce the mixed state.
118
+ - `state="disabled"` sets the native `disabled` attribute (the input leaves the tab order) and blocks pointer events on the whole element.
119
+ - Focus: `:focus-visible` on the hidden input draws a 2px `--rel-border-focus` outline with a 2px offset around the box.
120
+ - No live-region announcements are made; the native checkbox reports its own state changes.
121
+
122
+ | Key | Action |
123
+ | --- | --- |
124
+ | `Tab` / `Shift+Tab` | Move focus to / from the checkbox |
125
+ | `Space` | Toggle between checked and unchecked (native behaviour; indeterminate resolves to checked) |
126
+
127
+ ## Notes / Edge Cases
128
+
129
+ - User toggling is binary: indeterminate is never entered by interaction. Set `status="indeterminate"` programmatically (e.g. a Select-All parent driven by app state).
130
+ - `checked` is a convenience accessor over `status` (used by the Angular ControlValueAccessor wrapper); reading it is `status === "checked"`, writing it sets `"checked"` / `"unchecked"`.
131
+ - `alignment="trailing"` with `density="compact"` is "Not available" in the Figma sheet: the element renders comfortable density and logs `[rel-checkbox] density="compact" has no trailing layout; rendering comfortable density.` once per change.
132
+ - Comfortable density with no supporting text is visually identical to compact.
133
+ - The host is `display: block`, so a trailing checkbox stretches to its container width; constrain the parent to control row width.
134
+ - `value` is only reported in the `rel-change` detail — the element does not participate in native form submission. It is form-associated (so an outer `<label>` can find it) but sets no form value, so it is still not submitted and form reset does not touch it; it does now appear in `form.elements`.
135
+ - `el.click()` from script now toggles the checkbox, like a native one; it used to do nothing.
136
+ - The hidden native input is absolutely positioned against the `.row` containing block; keep `position: relative` on `.row` (Tab-scroll page-jump fix, shared with rel-radio).
137
+ - Control frames are 16 / 18 / 20 / 24px for small / medium / large / extra-large, matching Figma. The frame is the layout footprint — the row gap and the compact indent measure from it — while the drawn square is inset to 80% of the frame (12.8 / 14.4 / 16 / 19.2px), as Figma draws it. The square, its wall and the check / dash marks paint at the same size wherever the checkbox sits; before, the fractional squares were rounded to 12 or 13, 14 or 15, and 19 or 20px depending on the checkbox's sub-pixel position.
138
+ - The square's 2px border weight is **not** verified against Figma: the control is flattened artwork (a filled vector rather than a frame with a stroke), so the sheet gives the square's outer size but says nothing about its stroke. Carried forward from the previous implementation.
139
+
140
+ ### Layout matrix (mirrors the Figma sheet)
141
+
142
+ | Size | Density | Leading | Trailing |
143
+ | --- | --- | --- | --- |
144
+ | M | Comfortable | yes | yes |
145
+ | M | Compact | yes (default) | renders comfortable |
146
+ | S | Comfortable | yes | yes |
147
+ | S | Compact | yes | renders comfortable |
148
+ | L | Comfortable | yes | yes |
149
+ | L | Compact | yes | renders comfortable |
150
+ | XL | Comfortable | yes | yes |
151
+ | XL | Compact | yes | renders comfortable |
152
+
153
+ ### Recipes (intentionally not component props)
154
+
155
+ - **Selectable list row**: `alignment="trailing"` checkbox inside a padded, hover-highlighted container.
156
+ - **Select All / nested group**: parent checkbox with `status="indeterminate"` wired to children in app state.
157
+ - **Selectable card**: `rel-card` wrapping a checkbox; toggle a selected border on `rel-change`.
158
+
159
+ See the Storybook Checkbox stories for working recipe markup.