@reliability-design/web 1.4.5 → 1.4.7

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 (142) hide show
  1. package/CHANGELOG.md +211 -49
  2. package/dist/components/rel-accordion/README.md +132 -132
  3. package/dist/components/rel-alert/README.md +145 -141
  4. package/dist/components/rel-autocomplete/README.md +156 -61
  5. package/dist/components/rel-avatar/README.md +116 -130
  6. package/dist/components/rel-badge/README.md +98 -93
  7. package/dist/components/rel-breadcrumb/README.md +96 -102
  8. package/dist/components/rel-button/README.md +160 -130
  9. package/dist/components/rel-calendar/README.md +109 -109
  10. package/dist/components/rel-card/README.md +75 -94
  11. package/dist/components/rel-cardmedia/README.md +100 -127
  12. package/dist/components/rel-carousel/README.md +184 -166
  13. package/dist/components/rel-checkbox/README.md +93 -75
  14. package/dist/components/rel-chip/README.md +132 -121
  15. package/dist/components/rel-container/README.md +107 -99
  16. package/dist/components/rel-date-picker/README.md +200 -289
  17. package/dist/components/rel-divider/README.md +78 -100
  18. package/dist/components/rel-drawer/README.md +187 -200
  19. package/dist/components/rel-kbd/README.md +141 -151
  20. package/dist/components/rel-menu/README.md +178 -151
  21. package/dist/components/rel-menubar/README.md +218 -329
  22. package/dist/components/rel-otp/README.md +170 -440
  23. package/dist/components/rel-pagination/README.md +100 -424
  24. package/dist/components/rel-popover/README.md +203 -568
  25. package/dist/components/rel-progress/README.md +88 -110
  26. package/dist/components/rel-radio/README.md +131 -135
  27. package/dist/components/rel-range-picker/README.md +162 -0
  28. package/dist/components/rel-resizable/README.md +199 -140
  29. package/dist/components/rel-segmented-button/README.md +155 -141
  30. package/dist/components/rel-select/README.md +154 -93
  31. package/dist/components/rel-sheet/README.md +168 -224
  32. package/dist/components/rel-skeleton/README.md +103 -0
  33. package/dist/components/rel-slider/README.md +130 -135
  34. package/dist/components/rel-snackbar/README.md +162 -134
  35. package/dist/components/rel-stepper/README.md +158 -160
  36. package/dist/components/rel-switch/README.md +108 -102
  37. package/dist/components/rel-tab/README.md +171 -163
  38. package/dist/components/rel-textfield/README.md +159 -69
  39. package/dist/components/rel-time-picker/README.md +122 -157
  40. package/dist/components/rel-toast/README.md +157 -148
  41. package/dist/components/rel-tooltip/README.md +108 -103
  42. package/dist/components/rel-upload/README.md +220 -0
  43. package/dist/index.d.mts +1387 -350
  44. package/dist/index.d.ts +1387 -350
  45. package/dist/index.js +5863 -3600
  46. package/dist/index.js.map +1 -1
  47. package/dist/index.mjs +5864 -3592
  48. package/dist/index.mjs.map +1 -1
  49. package/dist/styles/vars.css +877 -866
  50. package/dist/{vars-XNMTSRVN.css → vars-JHTUGNRG.css} +877 -866
  51. package/package.json +4 -3
  52. package/dist/components/rel-accordion/rel-accordion.ts +0 -336
  53. package/dist/components/rel-alert/rel-alert.ts +0 -305
  54. package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -689
  55. package/dist/components/rel-avatar/rel-avatar.ts +0 -142
  56. package/dist/components/rel-badge/rel-badge.ts +0 -170
  57. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
  58. package/dist/components/rel-button/rel-button.ts +0 -560
  59. package/dist/components/rel-calendar/index.ts +0 -1
  60. package/dist/components/rel-calendar/rel-calendar.ts +0 -519
  61. package/dist/components/rel-card/rel-card.ts +0 -88
  62. package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
  63. package/dist/components/rel-carousel/index.ts +0 -1
  64. package/dist/components/rel-carousel/rel-carousel.ts +0 -700
  65. package/dist/components/rel-chart/README.md +0 -286
  66. package/dist/components/rel-chart/index.ts +0 -1
  67. package/dist/components/rel-chart/rel-chart.ts +0 -754
  68. package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
  69. package/dist/components/rel-chip/rel-chip.ts +0 -472
  70. package/dist/components/rel-container/rel-container.ts +0 -95
  71. package/dist/components/rel-date-picker/date-format.test.ts +0 -43
  72. package/dist/components/rel-date-picker/date-format.ts +0 -47
  73. package/dist/components/rel-date-picker/index.ts +0 -1
  74. package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1237
  75. package/dist/components/rel-divider/rel-divider.ts +0 -54
  76. package/dist/components/rel-drawer/index.ts +0 -1
  77. package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
  78. package/dist/components/rel-drawer/rel-drawer.ts +0 -604
  79. package/dist/components/rel-kbd/rel-kbd.ts +0 -188
  80. package/dist/components/rel-layout/rel-layout.ts +0 -49
  81. package/dist/components/rel-menu/rel-menu.ts +0 -535
  82. package/dist/components/rel-menubar/index.ts +0 -2
  83. package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
  84. package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
  85. package/dist/components/rel-menubar/rel-menubar.ts +0 -777
  86. package/dist/components/rel-nav-menu/README.md +0 -289
  87. package/dist/components/rel-nav-menu/index.ts +0 -3
  88. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
  89. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
  90. package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
  91. package/dist/components/rel-navbar/README.md +0 -126
  92. package/dist/components/rel-navbar/rel-navbar.ts +0 -105
  93. package/dist/components/rel-otp/index.ts +0 -1
  94. package/dist/components/rel-otp/rel-otp.ts +0 -517
  95. package/dist/components/rel-pagination/index.ts +0 -1
  96. package/dist/components/rel-pagination/rel-pagination.ts +0 -509
  97. package/dist/components/rel-popover/index.ts +0 -2
  98. package/dist/components/rel-popover/rel-popover-content.ts +0 -81
  99. package/dist/components/rel-popover/rel-popover.ts +0 -444
  100. package/dist/components/rel-progress/rel-progress.ts +0 -225
  101. package/dist/components/rel-radio/rel-radio.ts +0 -305
  102. package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1331
  103. package/dist/components/rel-resizable/index.ts +0 -3
  104. package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
  105. package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
  106. package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
  107. package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -213
  108. package/dist/components/rel-select/rel-select.ts +0 -1385
  109. package/dist/components/rel-sheet/rel-sheet.ts +0 -465
  110. package/dist/components/rel-sidebar/README.md +0 -209
  111. package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1185
  112. package/dist/components/rel-skeleton/rel-skeleton.ts +0 -134
  113. package/dist/components/rel-slider/rel-slider.ts +0 -670
  114. package/dist/components/rel-snackbar/rel-snackbar.ts +0 -325
  115. package/dist/components/rel-stepper/rel-stepper.ts +0 -565
  116. package/dist/components/rel-switch/rel-switch.ts +0 -197
  117. package/dist/components/rel-tab/rel-tab.ts +0 -264
  118. package/dist/components/rel-table/README.md +0 -178
  119. package/dist/components/rel-table/rel-table-body.ts +0 -22
  120. package/dist/components/rel-table/rel-table-caption.ts +0 -30
  121. package/dist/components/rel-table/rel-table-cell.ts +0 -43
  122. package/dist/components/rel-table/rel-table-footer.ts +0 -24
  123. package/dist/components/rel-table/rel-table-head.ts +0 -47
  124. package/dist/components/rel-table/rel-table-header.ts +0 -22
  125. package/dist/components/rel-table/rel-table-row.ts +0 -37
  126. package/dist/components/rel-table/rel-table.ts +0 -62
  127. package/dist/components/rel-textfield/rel-textfield.ts +0 -866
  128. package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1126
  129. package/dist/components/rel-toast/rel-toast.ts +0 -204
  130. package/dist/components/rel-tooltip/rel-tooltip.ts +0 -190
  131. package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
  132. package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
  133. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
  134. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
  135. package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
  136. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
  137. package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
  138. package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
  139. package/dist/components/rel-topbar/rel-topbar.ts +0 -446
  140. package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
  141. package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
  142. package/dist/components/rel-upload/rel-upload.ts +0 -943
@@ -1,160 +1,158 @@
1
- # rel-stepper
2
-
3
- ## Overview
4
- A comprehensive stepper component for visualizing multi-step processes. Supports horizontal and vertical orientations, text positioning (below or right of indicator), two size variants, and three step states (done, progress, disabled). Features clickable steps, automatic connector lines, and checkmark icons for completed steps.
5
-
6
- ## Usage
7
- ```html
8
- <!-- Basic horizontal stepper -->
9
- <rel-stepper id="checkout"></rel-stepper>
10
- <script>
11
- const stepper = document.getElementById('checkout');
12
- stepper.steps = [
13
- { title: 'Cart', status: 'done' },
14
- { title: 'Shipping', status: 'progress' },
15
- { title: 'Payment', status: 'disabled' },
16
- { title: 'Confirmation', status: 'disabled' }
17
- ];
18
- </script>
19
-
20
- <!-- Vertical stepper with text to the right -->
21
- <rel-stepper
22
- id="onboarding"
23
- orientation="vertical"
24
- textAlign="right">
25
- </rel-stepper>
26
- <script>
27
- const onboarding = document.getElementById('onboarding');
28
- onboarding.steps = [
29
- { title: 'Create Account', status: 'done' },
30
- { title: 'Verify Email', status: 'done' },
31
- { title: 'Profile Setup', status: 'progress' },
32
- { title: 'Complete', status: 'disabled' }
33
- ];
34
- </script>
35
-
36
- <!-- Small size horizontal stepper -->
37
- <rel-stepper
38
- id="wizard"
39
- size="small"
40
- textAlign="below">
41
- </rel-stepper>
42
- <script>
43
- const wizard = document.getElementById('wizard');
44
- wizard.steps = [
45
- { title: 'Select', status: 'done' },
46
- { title: 'Configure', status: 'progress' },
47
- { title: 'Review', status: 'disabled' }
48
- ];
49
- </script>
50
-
51
- <!-- Listen for step clicks -->
52
- <rel-stepper id="interactive"></rel-stepper>
53
- <script>
54
- const interactive = document.getElementById('interactive');
55
- interactive.steps = [
56
- { title: 'Step 1', status: 'done' },
57
- { title: 'Step 2', status: 'progress' },
58
- { title: 'Step 3', status: 'disabled' }
59
- ];
60
- interactive.addEventListener('step-change', (e) => {
61
- console.log('Clicked step:', e.detail.index, e.detail.step);
62
- // Update step statuses or navigate to step content
63
- });
64
- </script>
65
- ```
66
-
67
- ## API
68
-
69
- ### Attributes/Properties
70
- | Name | Type | Default | Description |
71
- |------|------|---------|-------------|
72
- | `steps` | `Step[]` | `[]` | Array of step items (see Step interface below) |
73
- | `textAlign` | `"right" \| "below"` | `"below"` | Position of step labels relative to indicators |
74
- | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction |
75
- | `size` | `"small" \| "large"` | `"large"` | Size variant (controls connector line length and spacing) |
76
-
77
- ### Step Interface
78
- ```typescript
79
- interface Step {
80
- title: string; // Step label text
81
- status: "done" | "progress" | "disabled"; // Step state
82
- }
83
- ```
84
-
85
- ## Events
86
- | Event | Detail | Description |
87
- |-------|--------|-------------|
88
- | `step-change` | `{ index: number, step: Step }` | Fired when a non-disabled step is clicked |
89
-
90
- ## Slots
91
- Default slot not used.
92
-
93
- ## CSS Parts
94
- None exposed.
95
-
96
- ## Tokens / CSS Variables
97
-
98
- ### Semantic Tokens
99
- - `--rel-fonts-font-family` - Font family
100
- - `--rel-body-sm-regular-font-size` - Label font size
101
- - `--rel-fonts-weight-body-medium` - Default label font weight
102
- - `--rel-fonts-weight-body-semibold` - Active/done label font weight
103
-
104
- ### Spacing Tokens
105
- - `--rel-spacing-2xs` - Gap between indicators and labels (text-right mode)
106
-
107
- ### Color Tokens
108
- - `--rel-bg-surface` - Indicator background (progress, disabled states)
109
- - `--rel-text-default` - Active/done indicator background, text, and connector color
110
- - `--rel-border-default` - Disabled indicator border and inactive connector
111
- - `--rel-bg-surface-elevated` - Disabled indicator background
112
- - `--rel-text-disabled` - Disabled label text color
113
- - `--rel-text-default` - Default label text color
114
-
115
- ## Accessibility
116
- - Steps can be clicked unless in disabled state
117
- - Checkmark SVG uses `currentColor` for proper theming
118
- - Focus states could be enhanced with keyboard navigation (not currently implemented)
119
-
120
- ### Keyboard Interactions
121
- - Click-based interaction only (no keyboard navigation implemented)
122
-
123
- ### Focus Behavior
124
- - No specific focus handling (steps are div elements, not buttons)
125
-
126
- ## Notes / Edge Cases
127
- - **Indicator states**:
128
- - **done**: Black circle with white checkmark SVG icon
129
- - **progress**: White circle with black border and step number
130
- - **disabled**: Light gray circle with gray border and step number
131
-
132
- - **Connector lines**:
133
- - Positioned absolutely relative to the indicator
134
- - **Horizontal**: 2px height, extends from indicator to next step
135
- - **Vertical**: 2px width, extends from indicator to next step
136
- - **done/progress** connectors are black; **disabled** connectors are gray
137
- - Last step has no connector
138
-
139
- - **Size variants** (control connector length and gap):
140
- - **large horizontal**: 86px connector, 86px gap
141
- - **small horizontal**: 60px connector, 60px gap
142
- - **large vertical**: 86px connector, 86px gap
143
- - **small vertical**: 42px connector, 42px gap
144
-
145
- - **Text positioning**:
146
- - **below**: Labels appear centered below indicators
147
- - **right**: Labels appear to the right of indicators with a small gap
148
-
149
- - **Layout combinations**:
150
- - **horizontal + text-below**: Steps arranged in a row, labels centered below
151
- - **horizontal + text-right**: Steps in a row, labels to the right of each indicator
152
- - **vertical + text-below**: Steps stacked vertically, labels centered below each indicator
153
- - **vertical + text-right**: Steps stacked vertically, labels to the right with indicators on the left
154
-
155
- - The indicator is 22px × 22px with a 2px border
156
- - Step numbers are 1-indexed (displayed as `index + 1`)
157
- - Clicking a disabled step does nothing (no event dispatched)
158
- - All transitions use `0.2s ease`
159
- - The component uses flexbox extensively for layout management
160
- - The stepper is `display: block` and `width: 100%`
1
+ # rel-stepper
2
+
3
+ A multi-step progress indicator implementing the Figma "Stepper" component: its `Type` axis (default, dot, number, icon indicators), its `Typel` label-placement axis (top, centered, inverted), two sizes and both orientations. Each entry in `steps` renders as a focusable step with a circular indicator, a label and a connector to the next step, styled by its status (`done`, `progress`, `disabled`). Use it to show where the user is in a linear flow (checkout, onboarding, a wizard) and to let them jump back to completed steps; the component is presentation only — it never changes a step's status itself, so drive `steps` from your own state.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Horizontal (default), labels under the indicators -->
9
+ <rel-stepper id="checkout"></rel-stepper>
10
+ <script>
11
+ document.getElementById('checkout').steps = [
12
+ { title: 'Cart', status: 'done' },
13
+ { title: 'Shipping', status: 'progress' },
14
+ { title: 'Payment', status: 'disabled' },
15
+ { title: 'Confirmation', status: 'disabled' }
16
+ ];
17
+ </script>
18
+
19
+ <!-- Vertical, small, label beside the indicator (Figma Typel = Centered) -->
20
+ <rel-stepper id="onboarding" orientation="vertical" label-placement="centered" size="small"></rel-stepper>
21
+ <script>
22
+ document.getElementById('onboarding').steps = [
23
+ { title: 'Create account', status: 'done' },
24
+ { title: 'Verify email', status: 'done' },
25
+ { title: 'Set up profile', status: 'progress' },
26
+ { title: 'Done', status: 'disabled' }
27
+ ];
28
+ </script>
29
+
30
+ <!-- Figma Type axis: dot / number / icon indicators -->
31
+ <rel-stepper type="dot" steps='[{"title":"Plan","status":"done"},{"title":"Build","status":"progress"},{"title":"Ship","status":"disabled"}]'></rel-stepper>
32
+ <rel-stepper type="number" steps='[{"title":"Plan","status":"done"},{"title":"Build","status":"progress"},{"title":"Ship","status":"disabled"}]'></rel-stepper>
33
+ <rel-stepper type="icon" steps='[{"title":"Plan","status":"done"},{"title":"Build","status":"progress"},{"title":"Ship","status":"disabled"}]'></rel-stepper>
34
+
35
+ <!-- Label placement (Figma Typel): top-aligned beside the indicator, or indicator above the label -->
36
+ <rel-stepper orientation="vertical" label-placement="top" steps='[{"title":"Review","status":"done"},{"title":"Approve","status":"progress"}]'></rel-stepper>
37
+ <rel-stepper label-placement="inverted" steps='[{"title":"Review","status":"done"},{"title":"Approve","status":"progress"}]'></rel-stepper>
38
+
39
+ <!-- Let users jump back to a completed step -->
40
+ <rel-stepper id="wizard"></rel-stepper>
41
+ <script>
42
+ const wizard = document.getElementById('wizard');
43
+ wizard.steps = [
44
+ { title: 'Select', status: 'done' },
45
+ { title: 'Configure', status: 'progress' },
46
+ { title: 'Review', status: 'disabled' }
47
+ ];
48
+ wizard.addEventListener('rel-step-change', (e) => {
49
+ console.log('Activated step', e.detail.index, e.detail.step.title);
50
+ // Recompute statuses and assign a new array so the stepper re-renders
51
+ wizard.steps = wizard.steps.map((s, i) => ({
52
+ ...s,
53
+ status: i < e.detail.index ? 'done' : i === e.detail.index ? 'progress' : 'disabled'
54
+ }));
55
+ });
56
+ </script>
57
+ ```
58
+
59
+ ### Deprecated aliases
60
+
61
+ ```html
62
+ <!-- textalign="right" → label-placement="centered"; textalign="below" → label-placement="inverted".
63
+ Still supported and still the fallback when label-placement is unset; no console notice is logged. -->
64
+ <rel-stepper textalign="right" steps='[{"title":"Review","status":"done"},{"title":"Approve","status":"progress"}]'></rel-stepper>
65
+ ```
66
+
67
+ The `Step` type and the `StepStatus`, `StepperType` and `LabelPlacement` unions are exported from the package:
68
+
69
+ ```typescript
70
+ import type { Step } from '@reliability-design/web';
71
+
72
+ const steps: Step[] = [
73
+ { title: 'Cart', status: 'done' }, // filled indicator with a check mark
74
+ { title: 'Shipping', status: 'progress' }, // current step (aria-current="step")
75
+ { title: 'Payment', status: 'disabled' } // not yet reachable; rendered at 40% opacity, not focusable
76
+ ];
77
+ ```
78
+
79
+ <!-- readme-gen:start -->
80
+
81
+ <!-- Generated from rel-stepper.ts — do not edit; run readme-generate.mjs -->
82
+
83
+ ## API
84
+
85
+ ### Attributes / Properties
86
+
87
+ | Property | Attribute | Type | Default | Description |
88
+ | --- | --- | --- | --- | --- |
89
+ | `steps` | `steps` | `Step[]` | `[]` | The steps in order, each `{ title: string; status: "done" \| "progress" \| "disabled" }`. Set as a property (or a JSON array attribute); the component never mutates it — update it from the `rel-step-change` handler. |
90
+ | `orientation` | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout axis: `horizontal` (default) lays the steps out in a centred row; `vertical` stacks them. |
91
+ | `size` | `size` | `"small" \| "large"` | `"large"` | `large` (default) or `small`: controls the label type (body-md vs body-sm) and the connector length / step gap (see the `--rel-stepper-connector-length-*` hooks). |
92
+ | `type` | `type` | `"default" \| "dot" \| "number" \| "icon"` | `"default"` | Figma "Type" axis — what the indicator shows: `default` (step number, check mark once done), `dot` (8px dot, no glyph), `number` (always the number) or `icon` (always the check mark). Reflected. |
93
+ | `labelPlacement` | `label-placement` | `"top" \| "centered" \| "inverted"` | `undefined` | Figma "Typel" axis — where the label sits: `top` (top-aligned beside the indicator), `centered` (vertically centred beside it) or `inverted` (indicator above the label). When unset, the deprecated `textAlign` prop drives the layout (`below` ≈ `inverted`, `right` ≈ `centered`). Figma marks Top + Horizontal as an unsupported combination. Reflected. |
94
+
95
+ #### Deprecated (still supported — removal targeted for 3.0)
96
+
97
+ | Property | Attribute | Type | Use instead |
98
+ | --- | --- | --- | --- |
99
+ | `textAlign` | `textalign` | `"right" \| "below"` | Deprecated alias of `label-placement`; use `label-placement="inverted"` instead of `textalign="below"` and `label-placement="centered"` instead of `textalign="right"`. |
100
+
101
+ ## Events
102
+
103
+ | Event | Detail | Bubbles / composed | Description |
104
+ | --- | --- | --- | --- |
105
+ | `rel-step-change` | `{ index, step, }` | bubbles / composed | Fired when a step whose status is not `disabled` is clicked or activated with Enter / Space. Detail: `{ index: number, step: Step }`. Statuses are not changed by the component — update `steps` in the handler. |
106
+
107
+ ## Slots
108
+
109
+ | Slot | Description |
110
+ | --- | --- |
111
+ | — | This element has no slots. |
112
+
113
+ ## CSS Parts
114
+
115
+ | Part | Description |
116
+ | --- | --- |
117
+ | `indicator` | The 24px circle (8px for `type="dot"`) that holds the step number, check mark or icon. |
118
+ | `track` | The 1px connector line from a step to the next one (not rendered on the last step). |
119
+ | `label` | The step title text. |
120
+
121
+ ## Tokens / CSS Variables
122
+
123
+ ### Component hooks
124
+
125
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
126
+
127
+ | Custom property | Default | Description |
128
+ | --- | --- | --- |
129
+ | `--rel-stepper-connector-length-lg` | `86px` | Connector length and step gap for `size="large"` in both orientations (default 86px). |
130
+ | `--rel-stepper-connector-length-md` | `60px` | Connector length and step gap for `size="small"` in `orientation="horizontal"` (default 60px). |
131
+ | `--rel-stepper-connector-length-sm` | `42px` | Connector length and step gap for `size="small"` in `orientation="vertical"` (default 42px). |
132
+ | `--rel-stepper-indicator-size` | `24px` | Indicator diameter (default 24px; `type="dot"` is fixed at 8px). |
133
+
134
+ <!-- readme-gen:end -->
135
+
136
+ ## Accessibility
137
+
138
+ - The list renders as a `role="group"` with the fixed name "Progress steps" (not configurable).
139
+ - Every step is a `role="button"` element with `aria-label="<title>, step n of N"`, plus ", completed" for `done` steps. The `progress` step carries `aria-current="step"`; `disabled` steps carry `aria-disabled="true"` and `tabindex="-1"` so they are skipped in the Tab order and by the arrow keys.
140
+ - Enabled steps are individual Tab stops (`tabindex="0"`) with a 2px focus ring; the indicators and connectors are purely visual (the check mark SVG is `aria-hidden`).
141
+ - Activating a step only emits `rel-step-change`; nothing is announced and no status changes until you update `steps`.
142
+
143
+ | Key | Action |
144
+ | --- | --- |
145
+ | `Enter` / `Space` | Activate the focused step (emits `rel-step-change`; ignored on `disabled` steps) |
146
+ | `ArrowRight` / `ArrowDown` | Move focus to the next enabled step (wraps to the first) |
147
+ | `ArrowLeft` / `ArrowUp` | Move focus to the previous enabled step (wraps to the last) |
148
+ | `Home` / `End` | Move focus to the first / last enabled step |
149
+
150
+ ## Notes / Edge Cases
151
+
152
+ - `label-placement` is the canonical layout switch (Figma `Typel`). When it is unset the deprecated `textalign` prop decides: `below` renders like `inverted` (indicator above the label), `right` renders like `centered` (label beside the indicator). `top` differs from `centered` only in aligning the label to the top of the indicator. Figma marks Top + Horizontal as an unsupported combination.
153
+ - Statuses map to the Figma `.Artwork` states: `done` = inverse fill with a check mark (or the number when `type="number"`, nothing when `type="dot"`), `progress` = neutral fill with a strong 1px border, `disabled` = the same drawn at 40% opacity. Connectors are `border-strong` after a `done` / `progress` step and `border-default` otherwise.
154
+ - `type="icon"` shows the check mark on every step regardless of status; `type="dot"` shrinks the indicator to 8px and fills it for `done` and `progress`.
155
+ - Connector length doubles as the gap between steps and depends on `size` and `orientation`: large = `--rel-stepper-connector-length-lg` (86px) in both orientations; small horizontal = `--rel-stepper-connector-length-md` (60px); small vertical = `--rel-stepper-connector-length-sm` (42px). Note the `md` / `sm` suffixes refer to those defaults, not to a size value.
156
+ - Labels never wrap (`white-space: nowrap`); keep titles short or widen the connector hooks.
157
+ - `steps` is compared by reference: mutate-in-place changes are not picked up — assign a new array.
158
+ - Steps are `<div role="button">` elements, not native buttons, so they do not submit forms and do not get native disabled styling.
@@ -1,102 +1,108 @@
1
- # rel-switch
2
-
3
- ## Overview
4
- A toggle switch component for binary on/off states. Features smooth animations, focus halo effects, pressed states, and respects user motion preferences. Built with custom visual styling while maintaining native checkbox accessibility.
5
-
6
- ## Usage
7
- ```html
8
- <!-- Basic switch -->
9
- <rel-switch></rel-switch>
10
-
11
- <!-- Pre-checked switch -->
12
- <rel-switch checked></rel-switch>
13
-
14
- <!-- Disabled switch -->
15
- <rel-switch disabled></rel-switch>
16
- <rel-switch checked disabled></rel-switch>
17
-
18
- <!-- With event listener -->
19
- <rel-switch id="notifications"></rel-switch>
20
- <script>
21
- const toggle = document.getElementById('notifications');
22
- toggle.addEventListener('changed', (e) => {
23
- console.log('Switch state:', e.detail); // boolean: true/false
24
- });
25
- </script>
26
-
27
- <!-- Programmatically control -->
28
- <rel-switch id="darkMode"></rel-switch>
29
- <script>
30
- const darkModeSwitch = document.getElementById('darkMode');
31
- darkModeSwitch.checked = true;
32
- darkModeSwitch.disabled = false;
33
- </script>
34
- ```
35
-
36
- ## API
37
-
38
- ### Attributes/Properties
39
- | Name | Type | Default | Description |
40
- |------|------|---------|-------------|
41
- | `checked` | `boolean` | `false` | Whether the switch is in the ON position |
42
- | `disabled` | `boolean` | `false` | Disables the switch and reduces opacity |
43
-
44
- ## Events
45
- | Event | Detail | Description |
46
- |-------|--------|-------------|
47
- | `changed` | `boolean` (the new checked state) | Fired when the switch is toggled by user interaction |
48
-
49
- ## Slots
50
- Default slot not used.
51
-
52
- ## CSS Parts
53
- None exposed.
54
-
55
- ## Tokens / CSS Variables
56
-
57
- ### Component-Level Custom Properties
58
- The component defines these CSS custom properties on `:host` which can be overridden:
59
-
60
- - `--switch-track` - Track color when unchecked (default: `--rel-text-placeholder`)
61
- - `--switch-knob-on` - Knob color when checked (default: `--rel-text-default`)
62
- - `--switch-knob-off` - Knob color when unchecked (default: `--rel-bg-surface`)
63
- - `--switch-halo` - Focus halo color (default: `--rel-border-default`)
64
- - `--switch-disabled` - Color for disabled state (default: `--rel-text-disabled`)
65
-
66
- ### Design Token References
67
- - `--rel-text-placeholder` - Default track color
68
- - `--rel-text-dark-placeholder` - Hover track color
69
- - `--rel-text-default` - ON knob color
70
- - `--rel-bg-surface` - OFF knob color
71
- - `--rel-border-default` - Focus halo
72
- - `--rel-text-disabled` - Disabled state color
73
- - `--rel-bg-neutral-elevated-1` - Used in disabled styling
74
-
75
- ## Accessibility
76
- - Uses native checkbox input with `role="switch"` and `aria-checked`
77
- - Visually hidden checkbox maintains keyboard and screen reader support
78
- - Focus visible state shows prominent halo around knob
79
- - Disabled state prevents interaction and reduces opacity to 0.5
80
- - Smooth transitions respect `prefers-reduced-motion` media query
81
-
82
- ### Keyboard Interactions
83
- - `Space` - Toggle switch on/off
84
- - `Tab` - Move focus to/from switch
85
-
86
- ### Focus Behavior
87
- - Focus ring appears as a 6px halo around the knob using `--switch-halo` color
88
- - Halo uses box-shadow for smooth visual feedback
89
-
90
- ### Motion Support
91
- - Animations disabled when `prefers-reduced-motion: reduce` is set
92
- - Transitions apply to track color, knob position, knob color, and box-shadow
93
-
94
- ## Notes / Edge Cases
95
- - The switch is 42px wide × 22px tall with a 12px tall track and 18px diameter knob
96
- - Visual knob animates 22px horizontally when toggling from OFF to ON
97
- - Hover effect only applies when not disabled (track darkens slightly)
98
- - Pressed state applies a `scale(0.9)` transform to the knob for tactile feedback
99
- - The knob includes a subtle drop shadow (`0 1px 3px rgba(0,0,0,0.3)`) for depth
100
- - When disabled, both track and knob use `--switch-disabled` color
101
- - The component is `display: inline-block` by default
102
- - Focus halo appears on keyboard focus only (`:focus-visible`), not on mouse click
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
+ | `disabled` | `disabled` | `boolean` | `false` | Disables interaction, dims the control to 50% and removes the handle shadow. |
48
+ | `value` | `value` | `string` | `""` | Arbitrary string echoed in the `rel-change` event detail — useful when one handler serves several switches. |
49
+ | `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. |
50
+
51
+ ## Events
52
+
53
+ | Event | Detail | Bubbles / composed | Description |
54
+ | --- | --- | --- | --- |
55
+ | `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 }`. |
56
+
57
+ ## Slots
58
+
59
+ | Slot | Description |
60
+ | --- | --- |
61
+ | — | This element has no slots. |
62
+
63
+ ## CSS Parts
64
+
65
+ | Part | Description |
66
+ | --- | --- |
67
+ | `base` | The `<label>` wrapper around the hidden input and the track |
68
+ | `track` | The thin rail; the handle is its `::before` pseudo-element |
69
+
70
+ ## Tokens / CSS Variables
71
+
72
+ ### Component hooks
73
+
74
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
75
+
76
+ | Custom property | Default | Description |
77
+ | --- | --- | --- |
78
+ | `--rel-switch-disabled` | `var(--switch-disabled)` | Handle colour while disabled; default `var(--rel-bg-neutral-elevated-1)` |
79
+ | `--rel-switch-knob-off` | `var(--switch-knob-off)` | Handle colour when unchecked; default `var(--rel-text-static-light)` |
80
+ | `--rel-switch-knob-on` | `var(--switch-knob-on)` | Handle colour when checked; default `var(--rel-bg-neutral-inverse-2)` |
81
+ | `--rel-switch-thumb-size` | `20px` | Handle diameter; default 20px (the handle always travels 20px) |
82
+ | `--rel-switch-track` | `var(--switch-track)` | Rail colour; default `var(--rel-bg-neutral-elevated-2)` |
83
+ | `--rel-switch-track-height` | `20px` | Overall control height; default 20px |
84
+ | `--rel-switch-track-width` | `44px` | Overall control width; default 44px |
85
+
86
+ <!-- readme-gen:end -->
87
+
88
+ ## Accessibility
89
+
90
+ - 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.
91
+ - `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.
92
+ - Focus: the wrapper shows a 1.5px focus outline whenever the input is focused (mouse or keyboard).
93
+ - `disabled` disables the native input (removed from the tab order), dims the control to 50% and drops the handle shadow.
94
+ - `prefers-reduced-motion: reduce` removes the track and handle transitions.
95
+
96
+ | Key | Action |
97
+ | --- | --- |
98
+ | `Space` | Toggles the switch (native checkbox behaviour). |
99
+ | `Tab` / `Shift+Tab` | Moves focus to / from the switch. |
100
+
101
+ ## Notes / Edge Cases
102
+
103
+ - `rel-change` fires for user toggles only; setting `checked` from JavaScript updates the visuals but emits nothing.
104
+ - Geometry is fixed to the Figma Line switch: 44×20 control, 40×10 track inset 2px, 20px handle. The handle always travels 20px, so changing `--rel-switch-track-width` widens the control without moving the "on" position.
105
+ - Figma's default Type=Pill switch (44×24 filled track with the handle inside) is not implemented.
106
+ - 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.
107
+ - 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.
108
+ - `registerOnChange`, `registerOnTouched` and `writeValue` exist for the Angular `ControlValueAccessor` wrapper and are not public API.