@reliability-design/web 1.4.6 → 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 (146) 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 -138
  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 -111
  42. package/dist/components/rel-upload/README.md +220 -0
  43. package/dist/index.d.mts +1147 -340
  44. package/dist/index.d.ts +1147 -340
  45. package/dist/index.js +3451 -3163
  46. package/dist/index.js.map +1 -1
  47. package/dist/index.mjs +3416 -3118
  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 +3 -2
  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 -720
  55. package/dist/components/rel-avatar/rel-avatar.ts +0 -142
  56. package/dist/components/rel-badge/rel-badge.ts +0 -175
  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 -565
  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 -723
  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 -483
  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/date-parse.test.ts +0 -116
  74. package/dist/components/rel-date-picker/date-parse.ts +0 -178
  75. package/dist/components/rel-date-picker/index.ts +0 -1
  76. package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1676
  77. package/dist/components/rel-divider/rel-divider.ts +0 -54
  78. package/dist/components/rel-drawer/index.ts +0 -1
  79. package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
  80. package/dist/components/rel-drawer/rel-drawer.ts +0 -607
  81. package/dist/components/rel-kbd/rel-kbd.ts +0 -188
  82. package/dist/components/rel-layout/rel-layout.ts +0 -49
  83. package/dist/components/rel-menu/rel-menu.ts +0 -541
  84. package/dist/components/rel-menubar/index.ts +0 -2
  85. package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
  86. package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
  87. package/dist/components/rel-menubar/rel-menubar.ts +0 -777
  88. package/dist/components/rel-nav-menu/README.md +0 -289
  89. package/dist/components/rel-nav-menu/index.ts +0 -3
  90. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
  91. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
  92. package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
  93. package/dist/components/rel-navbar/README.md +0 -126
  94. package/dist/components/rel-navbar/rel-navbar.ts +0 -105
  95. package/dist/components/rel-otp/index.ts +0 -1
  96. package/dist/components/rel-otp/rel-otp.ts +0 -527
  97. package/dist/components/rel-pagination/index.ts +0 -1
  98. package/dist/components/rel-pagination/rel-pagination.ts +0 -522
  99. package/dist/components/rel-popover/index.ts +0 -2
  100. package/dist/components/rel-popover/rel-popover-content.ts +0 -81
  101. package/dist/components/rel-popover/rel-popover.ts +0 -475
  102. package/dist/components/rel-progress/rel-progress.ts +0 -234
  103. package/dist/components/rel-radio/rel-radio.ts +0 -481
  104. package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1688
  105. package/dist/components/rel-resizable/index.ts +0 -3
  106. package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
  107. package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
  108. package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
  109. package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -217
  110. package/dist/components/rel-select/rel-select.ts +0 -1416
  111. package/dist/components/rel-sheet/rel-sheet.ts +0 -610
  112. package/dist/components/rel-sidebar/README.md +0 -209
  113. package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1191
  114. package/dist/components/rel-skeleton/rel-skeleton.ts +0 -143
  115. package/dist/components/rel-slider/rel-slider.ts +0 -673
  116. package/dist/components/rel-snackbar/rel-snackbar.ts +0 -329
  117. package/dist/components/rel-stepper/rel-stepper.ts +0 -567
  118. package/dist/components/rel-switch/rel-switch.ts +0 -199
  119. package/dist/components/rel-tab/rel-tab.ts +0 -264
  120. package/dist/components/rel-table/README.md +0 -178
  121. package/dist/components/rel-table/rel-table-body.ts +0 -22
  122. package/dist/components/rel-table/rel-table-caption.ts +0 -30
  123. package/dist/components/rel-table/rel-table-cell.ts +0 -43
  124. package/dist/components/rel-table/rel-table-footer.ts +0 -24
  125. package/dist/components/rel-table/rel-table-head.ts +0 -47
  126. package/dist/components/rel-table/rel-table-header.ts +0 -22
  127. package/dist/components/rel-table/rel-table-row.ts +0 -37
  128. package/dist/components/rel-table/rel-table.ts +0 -62
  129. package/dist/components/rel-textfield/rel-textfield.ts +0 -1054
  130. package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1482
  131. package/dist/components/rel-time-picker/time-parse.test.ts +0 -67
  132. package/dist/components/rel-time-picker/time-parse.ts +0 -85
  133. package/dist/components/rel-toast/rel-toast.ts +0 -206
  134. package/dist/components/rel-tooltip/rel-tooltip.ts +0 -193
  135. package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
  136. package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
  137. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
  138. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
  139. package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
  140. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
  141. package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
  142. package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
  143. package/dist/components/rel-topbar/rel-topbar.ts +0 -446
  144. package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
  145. package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
  146. package/dist/components/rel-upload/rel-upload.ts +0 -968
@@ -1,166 +1,184 @@
1
- # rel-carousel
2
-
3
- A fully accessible carousel component built with Lit for the Reliability Design System.
4
-
5
- ## Features
6
-
7
- - Horizontal sliding carousel
8
- - Touch/mouse drag support
9
- - Keyboard navigation
10
- - Optional autoplay
11
- - Navigation buttons and dot indicators
12
- - Loop mode
13
- - Smooth transitions with reduced motion support
14
- - Full ARIA support
15
-
16
- ## Usage
17
-
18
- ```html
19
- <rel-carousel>
20
- <div>Slide 1</div>
21
- <div>Slide 2</div>
22
- <div>Slide 3</div>
23
- </rel-carousel>
24
- ```
25
-
26
- ### With Loop
27
-
28
- ```html
29
- <rel-carousel loop>
30
- <div>Slide 1</div>
31
- <div>Slide 2</div>
32
- <div>Slide 3</div>
33
- </rel-carousel>
34
- ```
35
-
36
- ### With Autoplay
37
-
38
- ```html
39
- <rel-carousel autoplay interval="3000">
40
- <div>Slide 1</div>
41
- <div>Slide 2</div>
42
- <div>Slide 3</div>
43
- </rel-carousel>
44
- ```
45
-
46
- ### Without Navigation
47
-
48
- ```html
49
- <rel-carousel show-buttons="false" show-dots="false">
50
- <div>Slide 1</div>
51
- <div>Slide 2</div>
52
- <div>Slide 3</div>
53
- </rel-carousel>
54
- ```
55
-
56
- ### Programmatic Control (JavaScript)
57
-
58
- ```javascript
59
- const carousel = document.querySelector('rel-carousel');
60
-
61
- // Navigate to specific slide
62
- carousel.value = 2;
63
-
64
- // Listen to changes
65
- carousel.addEventListener('rel-change', (e) => {
66
- console.log('Current slide:', e.detail.value);
67
- });
68
- ```
69
-
70
- ## Attributes
71
-
72
- | Attribute | Type | Default | Description |
73
- |-----------|------|---------|-------------|
74
- | `value` | `number` | `0` | Current slide index (0-based) |
75
- | `loop` | `boolean` | `false` | Enable infinite loop |
76
- | `autoplay` | `boolean` | `false` | Enable automatic slide advancement |
77
- | `interval` | `number` | `5000` | Autoplay interval in milliseconds |
78
- | `pause-on-hover` | `boolean` | `true` | Pause autoplay on mouse hover |
79
- | `show-buttons` | `boolean` | `true` | Show prev/next navigation buttons |
80
- | `show-dots` | `boolean` | `true` | Show dot indicators |
81
- | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Carousel orientation (v1: horizontal only) |
82
- | `align` | `"start" \| "center" \| "end"` | `"center"` | Slide alignment in viewport |
83
- | `slides-per-view` | `number` | `1` | Number of slides visible at once (v1: 1 only) |
84
- | `gap` | `number` | - | Gap between slides in pixels (optional) |
85
- | `disabled` | `boolean` | `false` | Disable all interactions |
86
-
87
- ## Events
88
-
89
- | Event | Detail | Description |
90
- |-------|--------|-------------|
91
- | `rel-change` | `{ value: number }` | Fired when active slide changes |
92
-
93
- ## Keyboard Navigation
94
-
95
- - **Arrow Left**: Go to previous slide
96
- - **Arrow Right**: Go to next slide
97
- - **Home**: Go to first slide
98
- - **End**: Go to last slide
99
- - **Tab**: Navigate through carousel controls
100
-
101
- ## CSS Parts
102
-
103
- Use `::part()` to customize carousel appearance:
104
-
105
- ```css
106
- rel-carousel::part(viewport) {
107
- border-radius: 12px;
108
- }
109
-
110
- rel-carousel::part(prev-button),
111
- rel-carousel::part(next-button) {
112
- background: rgba(0, 0, 0, 0.5);
113
- color: white;
114
- }
115
-
116
- rel-carousel::part(dot) {
117
- width: 10px;
118
- height: 10px;
119
- }
120
- ```
121
-
122
- Available parts:
123
- - `viewport` - The carousel viewport container
124
- - `track` - The sliding track container
125
- - `prev-button` - Previous navigation button
126
- - `next-button` - Next navigation button
127
- - `dots` - Dots container
128
- - `dot` - Individual dot indicator
129
-
130
- ## Accessibility
131
-
132
- - Carousel uses `role="region"` with `aria-roledescription="carousel"`
133
- - Each slide has proper ARIA labels
134
- - Navigation buttons have descriptive `aria-label` attributes
135
- - Supports keyboard navigation
136
- - Respects `prefers-reduced-motion` user preference
137
-
138
- ## Styling
139
-
140
- The component uses design tokens from the Reliability Design System. All colors, spacing, and typography are inherited from CSS variables.
141
-
142
- Key tokens used:
143
- - `--rel-bg-*` / `--rel-text-*` / `--rel-border-*` semantic colors
144
- - `--rel-spacing-*` for spacing
145
- - `--rel-shadows-*` for shadows
146
- - `--rel-border-*` for borders
147
- - Focus outline uses `--rel-bg-info`
148
- - Active dot uses `--rel-bg-brand`
149
-
150
- ## Interaction
151
-
152
- ### Mouse/Touch Drag
153
- - Click and drag to swipe between slides
154
- - Threshold-based snap: swipe 20% of slide width to trigger navigation
155
- - Smooth animation on release
156
-
157
- ### Autoplay
158
- - Automatically advances slides at specified interval
159
- - Pauses on hover (configurable via `pause-on-hover`)
160
- - Pauses during manual interaction
161
- - Resumes after interaction ends
162
-
163
- ### Reduced Motion
164
- - Component respects `prefers-reduced-motion` media query
165
- - Disables or reduces transitions when user prefers reduced motion
166
- - Drag interactions remain functional but with instant snap
1
+ # rel-carousel
2
+
3
+ A slide carousel implementing the Figma "Carousel" component and its three axes — `Type` (Default, Only Indicators, Side Arrows, Bottom Arrows), `Orientation` (Horizontal, Vertical) and `Multi Panels` — plus the `Show Dots` property. It shows one or more slotted slides at a time in a horizontal or vertical viewport and moves between them with arrows, dot indicators, pointer drag / swipe, the keyboard, or autoplay. Use it for a small, ordered set of equally important panels (hero images, onboarding cards, testimonials); do not use it as a substitute for tabs or for content the user must read in full — hidden slides are not reachable by page search or by screen readers until they are shown.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Default type: slides only — swipe, drag or use the arrow keys -->
9
+ <rel-carousel label="Product photos">
10
+ <img src="/photos/front.jpg" alt="Front view">
11
+ <img src="/photos/side.jpg" alt="Side view">
12
+ <img src="/photos/back.jpg" alt="Back view">
13
+ </rel-carousel>
14
+
15
+ <!-- Figma Type axis: overlaid arrows + dots -->
16
+ <rel-carousel type="side-arrows" label="Highlights">
17
+ <div><h3>Fast setup</h3><p>Up and running in minutes.</p></div>
18
+ <div><h3>Secure by default</h3><p>Encrypted at rest and in transit.</p></div>
19
+ <div><h3>Works everywhere</h3><p>One component, every framework.</p></div>
20
+ </rel-carousel>
21
+
22
+ <!-- Dots flanked by arrows under the slide -->
23
+ <rel-carousel type="bottom-arrows" label="Testimonials">
24
+ <blockquote>"Saved us a week." — Ada</blockquote>
25
+ <blockquote>"Zero regressions." — Grace</blockquote>
26
+ </rel-carousel>
27
+
28
+ <!-- Dots only -->
29
+ <rel-carousel type="only-indicators" label="Tips">
30
+ <p>Tip 1</p>
31
+ <p>Tip 2</p>
32
+ <p>Tip 3</p>
33
+ </rel-carousel>
34
+
35
+ <!-- Arrows on their own: show-dots="false" suppresses the dots the type implies -->
36
+ <rel-carousel type="side-arrows" show-dots="false" label="Highlights">
37
+ <div>Fast setup</div>
38
+ <div>Secure by default</div>
39
+ </rel-carousel>
40
+
41
+ <!-- Loop and autoplay (3 s), 16px between slides, start on the second slide -->
42
+ <rel-carousel type="side-arrows" loop autoplay interval="3000" gap="16" value="1" label="Promotions">
43
+ <div>Spring sale</div>
44
+ <div>Free shipping</div>
45
+ <div>New arrivals</div>
46
+ </rel-carousel>
47
+
48
+ <!-- Figma Multi Panels: 1.5 panels leaves the next slide peeking in -->
49
+ <rel-carousel type="side-arrows" panels="1.5" label="Related products">
50
+ <div>Product A</div>
51
+ <div>Product B</div>
52
+ <div>Product C</div>
53
+ <div>Product D</div>
54
+ </rel-carousel>
55
+
56
+ <!-- Two whole panels at a time, no peek -->
57
+ <rel-carousel type="only-indicators" panels="2" label="Case studies">
58
+ <div>Case A</div>
59
+ <div>Case B</div>
60
+ <div>Case C</div>
61
+ <div>Case D</div>
62
+ </rel-carousel>
63
+
64
+ <!-- Vertical: the viewport height comes from --rel-carousel-height -->
65
+ <rel-carousel orientation="vertical" type="side-arrows" label="Timeline" style="--rel-carousel-height: 240px">
66
+ <div>2024</div>
67
+ <div>2025</div>
68
+ <div>2026</div>
69
+ </rel-carousel>
70
+
71
+ <!-- Programmatic control -->
72
+ <rel-carousel id="gallery" type="bottom-arrows" label="Gallery">
73
+ <div>A</div>
74
+ <div>B</div>
75
+ <div>C</div>
76
+ </rel-carousel>
77
+ <script>
78
+ const gallery = document.getElementById('gallery');
79
+ gallery.value = 2; // jump to the third slide
80
+ gallery.pauseOnHover = false; // default-true booleans are switched off via the property
81
+ gallery.addEventListener('rel-change', (e) => {
82
+ console.log('Current slide:', e.detail.value);
83
+ });
84
+ </script>
85
+ ```
86
+
87
+ <!-- readme-gen:start -->
88
+
89
+ <!-- Generated from rel-carousel.ts — do not edit; run readme-generate.mjs -->
90
+
91
+ ## API
92
+
93
+ ### Attributes / Properties
94
+
95
+ | Property | Attribute | Type | Default | Description |
96
+ | --- | --- | --- | --- | --- |
97
+ | `value` | `value` | `number` | `0` | Index of the current slide (0-based). Set it to jump; it is clamped to the slide count and reflected as an attribute. Reflected. |
98
+ | `loop` | `loop` | `boolean` | `false` | Wrap from the last slide to the first (and back) with a seamless clone transition instead of stopping at the ends. |
99
+ | `autoplay` | `autoplay` | `boolean` | `false` | Advance automatically every `interval` ms; implies looping and pauses while hovered (see `pause-on-hover`) or while focus is inside the carousel. |
100
+ | `interval` | `interval` | `number` | `5000` | Autoplay delay between slides, in milliseconds (default 5000). |
101
+ | `pauseOnHover` | `pause-on-hover` | `boolean` | `true` | Pause autoplay while the pointer is over the carousel or while dragging (default true; switch off via the property, e.g. `el.pauseOnHover = false`). |
102
+ | `showButtons` | `show-buttons` | `boolean` | `false` | Legacy toggle for the overlaid previous / next arrows; ignored whenever `type` is set. |
103
+ | `showDots` | `show-dots` | `boolean` | `undefined` | Figma "Show Dots" property. Tri-state: left off it defers to `type` (dots for every type except `default`, and nothing at all when `type` is unset too); `show-dots` turns them on; `show-dots="false"` turns them off even when `type` would have shown them. |
104
+ | `type` | `type` | `"default" \| "only-indicators" \| "side-arrows" \| "bottom-arrows"` | `undefined` | Figma "Type" axis. When set it drives which controls render: default = content only · only-indicators = dots · side-arrows = overlaid arrows + dots · bottom-arrows = dots flanked by arrows below the slide. When unset, the legacy show-buttons boolean applies unchanged. The dots a type implies can always be overridden by an explicit `show-dots`. Reflected. |
105
+ | `orientation` | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Slide axis: `horizontal` (default) translates the track left / right; `vertical` stacks slides in a fixed-height viewport (`--rel-carousel-height`) and translates up / down. Reflected. |
106
+ | `label` | `label` | `string` | `"Carousel"` | Accessible name of the carousel region (`aria-label` on the viewport); default "Carousel". |
107
+ | `gap` | `gap` | `number` | `8` | Space between consecutive slides in pixels (applied as the track `gap` and added to each slide step); default 8 (Figma `spacing/xs`), 0 = slides touch. |
108
+ | `panels` | `panels` | `number` | `1` | Figma "Multi Panels" axis, as a count: how many slides are visible at once (default 1). Fractions are allowed and produce a peek of the next slide — `panels="1.5"` reproduces the Figma Multi Panels=True variant. Navigation still advances one slide at a time. |
109
+ | `disabled` | `disabled` | `boolean` | `false` | Disables arrows, dots, drag and keyboard navigation, stops autoplay and renders the carousel at 60% opacity. Reflected. |
110
+
111
+ ## Events
112
+
113
+ | Event | Detail | Bubbles / composed | Description |
114
+ | --- | --- | --- | --- |
115
+ | `rel-change` | `{ value: this.value }` | bubbles / composed | Fired whenever the current slide changes (arrows, dots, drag, keyboard, autoplay or a loop wrap). Detail: `{ value: number }` — the new 0-based slide index. |
116
+
117
+ ## Slots
118
+
119
+ | Slot | Description |
120
+ | --- | --- |
121
+ | (default) | The slides: one light-DOM element per slide (each is sized to one panel and given `role="group"` / `aria-roledescription="slide"`). |
122
+
123
+ ## CSS Parts
124
+
125
+ | Part | Description |
126
+ | --- | --- |
127
+ | `${direction}-button` | The two arrow buttons, exposed as `prev-button` and `next-button` (`type="side-arrows"` overlays them on the viewport; `type="bottom-arrows"` inlines them in the dots row). |
128
+ | `viewport` | The focusable `role="region"` box that clips the track (also the keyboard target). |
129
+ | `track` | The flex row / column that translates to reveal the current slide. |
130
+ | `dots` | The indicator row under the viewport (also hosts the arrows for `type="bottom-arrows"`). |
131
+ | `dot-group` | The row of dots inside `dots` (for `type="bottom-arrows"` it is the middle child, between the two arrows). |
132
+ | `dot` | One indicator button per reachable position (per slide at `panels="1"`); the active one carries the `active` class and `aria-current="true"`. |
133
+
134
+ ## Tokens / CSS Variables
135
+
136
+ ### Component hooks
137
+
138
+ Set these on the host (or an ancestor) to customise the element without touching design tokens.
139
+
140
+ | Custom property | Default | Description |
141
+ | --- | --- | --- |
142
+ | `--rel-carousel-dot-size` | `8px` | Diameter of an inactive dot (default 8px). |
143
+ | `--rel-carousel-dot-size-active` | `16px` | Width of the active (brand-coloured, pill-shaped) dot (default 16px). |
144
+ | `--rel-carousel-height` | `320px` | Viewport height in `orientation="vertical"` (default 320px); the horizontal viewport takes the height of its tallest slide. |
145
+ | `--rel-carousel-nav-size` | `32px` | Width / height of the arrow buttons (default 32px, matching Figma; applies to both side and bottom arrows). |
146
+ | `--rel-carousel-slide-height` | `100%` | Written by the component on its own host to the computed panel height (used for vertical slides); not meant to be set by consumers. |
147
+ | `--rel-carousel-slide-width` | `100%` | Written by the component on its own host to the computed panel width (viewport width for `panels="1"`, a fraction of it above that); not meant to be set by consumers (an inline value is overwritten on resize). |
148
+
149
+ <!-- readme-gen:end -->
150
+
151
+ ## Accessibility
152
+
153
+ - The viewport renders with `role="region"`, `aria-roledescription="carousel"` and `aria-label` set from the `label` prop (default "Carousel"); give every carousel a meaningful `label`.
154
+ - Each slotted slide is decorated with `role="group"`, `aria-roledescription="slide"` and `aria-label="n of N"`; the clone slides used for looping are `aria-hidden="true"`.
155
+ - The arrow buttons are labelled "Previous slide" / "Next slide" and their chevrons are `aria-hidden`; each dot is labelled "Go to slide n" and the active dot carries `aria-current="true"`.
156
+ - The viewport is a single Tab stop (`tabindex="0"`); the arrows and dots that are rendered are ordinary buttons and follow it in the Tab order.
157
+ - Every user-initiated slide change is announced through the shared live region as "Slide n of N"; autoplay ticks are deliberately silent.
158
+ - Autoplay pauses while the pointer is over the carousel (`pause-on-hover`, default on) and while keyboard focus is anywhere inside it (WCAG 2.2.2 Pause, Stop, Hide); it resumes when focus leaves.
159
+ - Track transitions are disabled under `prefers-reduced-motion: reduce`; drag still snaps to the nearest slide, just without animation.
160
+
161
+ | Key | Action |
162
+ | --- | --- |
163
+ | `ArrowLeft` / `ArrowUp` | Previous slide (wraps when `loop` or `autoplay` is set) |
164
+ | `ArrowRight` / `ArrowDown` | Next slide (wraps when `loop` or `autoplay` is set) |
165
+ | `Home` | First slide |
166
+ | `End` | Last slide |
167
+ | `Tab` | Move between the viewport, the arrows and the dots |
168
+
169
+ Keys are handled on the viewport (and anything focused inside it) and are ignored while `disabled`.
170
+
171
+ ## Notes / Edge Cases
172
+
173
+ - `type` is the canonical control switch. When it is unset the legacy `show-buttons` boolean still decides whether arrows render; when it is set `show-buttons` is ignored (`type="default"` hides the arrows).
174
+ - `show-dots` is deliberately tri-state, because Figma's `Show Dots` is a property rather than part of the `Type` axis. Omit it and `type` decides, exactly as before; write `show-dots` to force the dots on; write `show-dots="false"` to force them off even for a `type` that would have shown them. Omitting it is what every pre-existing carousel does, so none of them change.
175
+ - `panels` implements the Figma `Multi Panels` axis. Each panel measures `(viewport − gap × (ceil(panels) − 1)) / panels` along the scroll axis — a viewport showing `n` panels contains `ceil(n) − 1` whole gaps, so at the Figma frame width of 350px with the default 8px gap, `panels="1.5"` yields exactly the 228px slide the design specifies.
176
+ - Navigation always advances one slide per step, never one page. Without `loop`, the track stops once the last slide is flush with the trailing edge instead of scrolling into empty space, so at `panels="1.5"` with three slides the reachable indices are `0` and `1`. The dot row follows that: one dot per reachable position, which is one per slide at `panels="1"` and whenever `loop` is on.
177
+ - Slides are sized by the component: every slotted element gets `width: var(--rel-carousel-slide-width)` (or the height equivalent in `orientation="vertical"`) with `!important`, where the variable is written on the host to the computed panel size. Style the inside of a slide freely, but do not rely on a slide's own `width` / `height`.
178
+ - `loop` and `autoplay` clone the edge slides into the shadow DOM so the wrap looks continuous — `ceil(panels)` of them at each end, since a viewport showing more than one panel would otherwise run out of slides mid-transition. `rel-change` still reports the real index (`0` … `N-1`) after the silent jump.
179
+ - Drag / swipe uses a 20% threshold of the panel size; shorter drags snap back. Dragging pauses autoplay (when `pause-on-hover` is on) and resumes it on release.
180
+ - `value` is clamped to the highest reachable index whenever the slot content changes; setting it out of range moves to the nearest valid slide.
181
+ - Arrows are 32px circles with a 16px chevron, matching Figma. Side arrows (`type="side-arrows"`) overlay the viewport at the vertical centre, inset 8px from the edge; bottom arrows (`type="bottom-arrows"`) sit inside the indicator row, 20px from the dots. Both are hand-rolled ghost-style buttons, not `<rel-button>`, and both are sized by `--rel-carousel-nav-size`. Per the published Figma set the arrows stay on the left and right edges in `orientation="vertical"` too.
182
+ - The active dot is a 16 × 8 fully-rounded brand pill and an inactive dot an 8px circle; `--rel-carousel-dot-size-active` and `--rel-carousel-dot-size` override them.
183
+ - The horizontal viewport takes the height of its tallest slide; the vertical viewport is a fixed `--rel-carousel-height` (320px) — set it to fit your content.
184
+ - Arrow buttons are exposed as `::part(prev-button)` and `::part(next-button)`; the indicator row is `::part(dots)`, the dots inside it `::part(dot-group)` and `::part(dot)`.
@@ -1,11 +1,11 @@
1
1
  # rel-checkbox
2
2
 
3
- ## Overview
4
- A tri-state checkbox component supporting checked, unchecked, and indeterminate states. Includes label, optional supporting text, and optional label prefix icon, with built-in error and disabled states. Supports two sizes, two densities, and leading/trailing box alignment — matching the Figma Checkbox sheet vocabulary (Size, Density, Alignment) verbatim.
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), `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`.
5
4
 
6
5
  ## Usage
6
+
7
7
  ```html
8
- <!-- Basic example -->
8
+ <!-- Basic -->
9
9
  <rel-checkbox label="Accept terms"></rel-checkbox>
10
10
 
11
11
  <!-- Supporting text, compact density (default: text on its own line, indented past the box) -->
@@ -31,95 +31,113 @@ A tri-state checkbox component supporting checked, unchecked, and indeterminate
31
31
  supportingtext="Weekly summary of load activity">
32
32
  </rel-checkbox>
33
33
 
34
- <!-- Small size -->
34
+ <!-- Sizes (medium is the default) -->
35
35
  <rel-checkbox size="small" label="Include archived"></rel-checkbox>
36
-
37
- <!-- Indeterminate (programmatic-only; user toggle resolves to checked/unchecked) -->
38
- <rel-checkbox label="Select all" status="indeterminate"></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>
39
52
  ```
40
53
 
54
+ <!-- readme-gen:start -->
55
+
56
+ <!-- Generated from rel-checkbox.ts — do not edit; run readme-generate.mjs -->
57
+
41
58
  ## API
42
59
 
43
- ### Attributes/Properties
44
- | Name | Type | Default | Description |
45
- |------|------|---------|-------------|
46
- | `label` | `string` | `"Label"` | Label text displayed next to the checkbox |
47
- | `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 |
48
- | `supportingtext` | `string` | `""` | Helper text; placement depends on `density` |
49
- | `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual and interaction state of the checkbox |
50
- | `status` | `"unchecked" \| "checked" \| "indeterminate"` | `"unchecked"` | Current check state. Indeterminate is programmatic-only |
51
- | `checked` | `boolean` (accessor) | `false` | Convenience accessor over `status` (used by the Angular CVA) |
52
- | `size` | `"small" \| "medium"` | `"medium"` | Control scale: medium = 18px box, body-lg label, body-sm supporting text; small = 14px box, body-md label, body-xs supporting text (reflected) |
53
- | `density` | `"compact" \| "comfortable"` | `"compact"` | Supporting-text layout: compact puts it on its own line under the row, indented past the box; comfortable stacks label + supporting text beside the box (reflected) |
54
- | `alignment` | `"leading" \| "trailing"` | `"leading"` | Box position: leading = before the label; trailing = far edge of the row. Trailing always renders comfortable density — compact+trailing is "Not available" in the Figma sheet, and a dev-mode `console.warn` fires if requested (reflected) |
55
- | `value` | `string` | `""` | Value reported in the `rel-change` event detail |
60
+ ### Attributes / Properties
56
61
 
57
- ### Layout matrix (mirrors the Figma sheet)
58
- | Size | Density | Leading | Trailing |
59
- |------|---------|---------|----------|
60
- | M | Comfortable | ✓ | ✓ |
61
- | M | Compact | ✓ (default) | — renders comfortable |
62
- | S | Comfortable | ✓ | ✓ |
63
- | S | Compact | ✓ | — renders comfortable |
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 control to 0.55 opacity. |
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"` | `"medium"` | Control scale (Figma Size). `"medium"` (default) = 18px box with body-lg label; `"small"` = 14px box with body-md label; `"large"` (Figma L, added 2026-09-04) = 20px box with body-lg label and body-sm supporting text — the same additive step rel-radio took for its large size. 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
+
74
+ ### Public fields / accessors
75
+
76
+ | Name | Type | Description |
77
+ | --- | --- | --- |
78
+ | `checked` | `boolean` | Boolean view of `status`: `true` when `status === "checked"`; setting it writes `"checked"` / `"unchecked"`. |
64
79
 
65
80
  ## Events
66
- | Event | Detail | Description |
67
- |-------|--------|-------------|
68
- | `rel-change` | `{ checked: boolean, value: string }` | Fired on user toggle (bubbles, composed) |
81
+
82
+ | Event | Detail | Bubbles / composed | Description |
83
+ | --- | --- | --- | --- |
84
+ | `rel-change` | `{ checked: this.status === "checked", value: this.value, }` | bubbles / composed | Fired after a user toggle. Detail: `{ checked: boolean, value: string }`. |
69
85
 
70
86
  ## Slots
71
- Default slot not used.
87
+
88
+ | Slot | Description |
89
+ | --- | --- |
90
+ | — | This element has no slots. |
72
91
 
73
92
  ## CSS Parts
74
- - `base` — outer wrapper
75
- - `label` — label text span
76
- - `helper` — supporting text span
77
-
78
- ## Tokens / CSS Variables
79
-
80
- ### Semantic Tokens
81
- - `--rel-fonts-font-family` - Font family
82
- - `--rel-body-lg-regular-*` / `--rel-body-sm-regular-*` - Label and supporting text type (medium size)
83
- - `--rel-body-md-regular-*` / `--rel-body-xs-regular-*` - Label and supporting text type (small size)
84
-
85
- ### Spacing Tokens
86
- - `--rel-spacing-xs` - Gap between box, icon, and label
87
- - `--rel-spacing-3xs` - Gap between label and supporting text (comfortable) / row and supporting text (compact)
88
-
89
- ### Color Tokens
90
- - `--rel-text-default` - Box border and label text color (rest)
91
- - `--rel-text-body` - Hover color for box, label, and icon
92
- - `--rel-bg-neutral-inverse-2` - Checked box fill and indeterminate dash
93
- - `--rel-text-inverse` - Checkmark color
94
- - `--rel-text-caption` - Supporting text color
95
- - `--rel-border-focus` - Focus outline color
96
- - `--rel-border-danger` / `--rel-action-danger-fill` / `--rel-text-danger` - Error state colors
93
+
94
+ | Part | Description |
95
+ | --- | --- |
96
+ | `base` | The outer wrapper that carries the `state` / `status` classes |
97
+ | `label` | The visible label text |
98
+ | `helper` | The supporting text (rendered beside the box in comfortable density, under the row in compact) |
99
+
100
+ <!-- readme-gen:end -->
97
101
 
98
102
  ## Accessibility
99
- - Uses visually hidden native checkbox input for screen reader support
100
- - Custom visual checkbox with proper focus indicators
101
- - Focus visible state with outline offset for keyboard users
102
- - Label click targets the checkbox for larger interaction area (in trailing alignment the whole row is clickable)
103
- - Disabled state communicated through opacity reduction and cursor change
104
103
 
105
- ### Keyboard Interactions
106
- - `Space` - Toggle checkbox state
107
- - `Tab` - Move focus to/from checkbox
104
+ - 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.
105
+ - `status="indeterminate"` sets the native `indeterminate` flag and `aria-checked="mixed"` on the input, so screen readers announce the mixed state.
106
+ - `state="disabled"` sets the native `disabled` attribute (the input leaves the tab order) and blocks pointer events on the whole element.
107
+ - Focus: `:focus-visible` on the hidden input draws a 2px `--rel-border-focus` outline with a 2px offset around the box.
108
+ - No live-region announcements are made; the native checkbox reports its own state changes.
108
109
 
109
- ### Focus Behavior
110
- - Focus outline appears with offset around the custom checkbox box
111
- - Uses focus border color for high contrast
110
+ | Key | Action |
111
+ | --- | --- |
112
+ | `Tab` / `Shift+Tab` | Move focus to / from the checkbox |
113
+ | `Space` | Toggle between checked and unchecked (native behaviour; indeterminate resolves to checked) |
112
114
 
113
115
  ## Notes / Edge Cases
114
- - User toggling is binary: indeterminate is never entered by interaction — toggling from indeterminate resolves to checked. Set `status="indeterminate"` programmatically (e.g. a Select-All parent driven by app state)
115
- - When `state="disabled"`, click events are blocked and opacity is reduced to 0.55
116
- - The host is `display: block`, so a trailing checkbox stretches to its container width; constrain the parent to control row width
117
- - Comfortable density with no supporting text is visually identical to compact
118
- - 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)
119
-
120
- ## Recipes (intentionally NOT component props)
121
- - **Selectable list row**: `alignment="trailing"` checkbox inside a padded, hover-highlighted container
122
- - **Select All / nested group**: parent checkbox with `status="indeterminate"` wired to children in app state
123
- - **Selectable card**: `rel-card` wrapping a checkbox; toggle a selected border on `rel-change`
116
+
117
+ - User toggling is binary: indeterminate is never entered by interaction. Set `status="indeterminate"` programmatically (e.g. a Select-All parent driven by app state).
118
+ - `checked` is a convenience accessor over `status` (used by the Angular ControlValueAccessor wrapper); reading it is `status === "checked"`, writing it sets `"checked"` / `"unchecked"`.
119
+ - `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.
120
+ - Comfortable density with no supporting text is visually identical to compact.
121
+ - The host is `display: block`, so a trailing checkbox stretches to its container width; constrain the parent to control row width.
122
+ - `value` is only reported in the `rel-change` detail — the element does not participate in native form submission.
123
+ - 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).
124
+ - Rendered box sizes are 18 / 22 / 24px (content + 2px border) for small / medium / large, against Figma's 16 / 18 / 20 outer frames — a known, unaudited oversize on S/M.
125
+
126
+ ### Layout matrix (mirrors the Figma sheet)
127
+
128
+ | Size | Density | Leading | Trailing |
129
+ | --- | --- | --- | --- |
130
+ | M | Comfortable | yes | yes |
131
+ | M | Compact | yes (default) | renders comfortable |
132
+ | S | Comfortable | yes | yes |
133
+ | S | Compact | yes | renders comfortable |
134
+ | L | Comfortable | yes | yes |
135
+ | L | Compact | yes | renders comfortable |
136
+
137
+ ### Recipes (intentionally not component props)
138
+
139
+ - **Selectable list row**: `alignment="trailing"` checkbox inside a padded, hover-highlighted container.
140
+ - **Select All / nested group**: parent checkbox with `status="indeterminate"` wired to children in app state.
141
+ - **Selectable card**: `rel-card` wrapping a checkbox; toggle a selected border on `rel-change`.
124
142
 
125
143
  See the Storybook Checkbox stories for working recipe markup.