@reliability-design/web 1.0.2 → 1.0.6

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 (145) hide show
  1. package/dist/components/rel-accordion/README.md +132 -0
  2. package/dist/components/rel-accordion/rel-accordion.ts +61 -29
  3. package/dist/components/rel-alert/README.md +141 -0
  4. package/dist/components/rel-alert/rel-alert.ts +110 -67
  5. package/dist/components/rel-avatar/README.md +119 -0
  6. package/dist/components/rel-avatar/rel-avatar.ts +8 -15
  7. package/dist/components/rel-badge/README.md +86 -0
  8. package/dist/components/rel-badge/rel-badge.ts +28 -21
  9. package/dist/components/rel-breadcrumb/README.md +102 -0
  10. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +24 -18
  11. package/dist/components/rel-button/README.md +130 -0
  12. package/dist/components/rel-button/rel-button.ts +39 -59
  13. package/dist/components/rel-calendar/README.md +109 -0
  14. package/dist/components/rel-calendar/index.ts +1 -0
  15. package/dist/components/rel-calendar/rel-calendar.ts +467 -0
  16. package/dist/components/rel-card/README.md +94 -0
  17. package/dist/components/rel-card/rel-card.ts +21 -11
  18. package/dist/components/rel-cardmedia/README.md +127 -0
  19. package/dist/components/rel-cardmedia/rel-cardmedia.ts +22 -18
  20. package/dist/components/rel-carousel/README.md +166 -0
  21. package/dist/components/rel-carousel/index.ts +1 -0
  22. package/dist/components/rel-carousel/rel-carousel.ts +469 -0
  23. package/dist/components/rel-chart/README.md +286 -0
  24. package/dist/components/rel-chart/index.ts +1 -0
  25. package/dist/components/rel-chart/rel-chart.ts +736 -0
  26. package/dist/components/rel-checkbox/README.md +77 -0
  27. package/dist/components/rel-checkbox/rel-checkbox.ts +36 -45
  28. package/dist/components/rel-chip/README.md +114 -0
  29. package/dist/components/rel-chip/rel-chip.ts +47 -122
  30. package/dist/components/rel-container/README.md +99 -0
  31. package/dist/components/rel-container/rel-container.ts +1 -6
  32. package/dist/components/rel-date-picker/README.md +253 -0
  33. package/dist/components/rel-date-picker/index.ts +1 -0
  34. package/dist/components/rel-date-picker/rel-date-picker.ts +916 -0
  35. package/dist/components/rel-divider/README.md +100 -0
  36. package/dist/components/rel-divider/rel-divider.ts +37 -37
  37. package/dist/components/rel-drawer/README.md +200 -0
  38. package/dist/components/rel-drawer/index.ts +1 -0
  39. package/dist/components/rel-drawer/rel-drawer.ts +621 -0
  40. package/dist/components/rel-kbd/README.md +151 -0
  41. package/dist/components/rel-kbd/rel-kbd.ts +118 -0
  42. package/dist/components/rel-layout/README.md +88 -0
  43. package/dist/components/rel-layout/rel-layout.ts +12 -14
  44. package/dist/components/rel-menu/README.md +151 -0
  45. package/dist/components/rel-menu/rel-menu.ts +18 -10
  46. package/dist/components/rel-menubar/README.md +329 -0
  47. package/dist/components/rel-menubar/index.ts +2 -0
  48. package/dist/components/rel-menubar/rel-menubar-menu.ts +16 -0
  49. package/dist/components/rel-menubar/rel-menubar.ts +576 -0
  50. package/dist/components/rel-nav-menu/README.md +289 -0
  51. package/dist/components/rel-nav-menu/index.ts +3 -0
  52. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +143 -0
  53. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +53 -0
  54. package/dist/components/rel-nav-menu/rel-nav-menu.ts +331 -0
  55. package/dist/components/rel-navbar/README.md +126 -0
  56. package/dist/components/rel-navbar/rel-navbar.ts +91 -0
  57. package/dist/components/rel-otp/README.md +440 -0
  58. package/dist/components/rel-otp/index.ts +1 -0
  59. package/dist/components/rel-otp/rel-otp.ts +504 -0
  60. package/dist/components/rel-pagination/README.md +410 -0
  61. package/dist/components/rel-pagination/index.ts +1 -0
  62. package/dist/components/rel-pagination/rel-pagination.ts +376 -0
  63. package/dist/components/rel-popover/README.md +568 -0
  64. package/dist/components/rel-popover/index.ts +2 -0
  65. package/dist/components/rel-popover/rel-popover-content.ts +55 -0
  66. package/dist/components/rel-popover/rel-popover.ts +327 -0
  67. package/dist/components/rel-progress/README.md +110 -0
  68. package/dist/components/rel-progress/rel-progress.ts +58 -20
  69. package/dist/components/rel-quote-page/README.md +166 -0
  70. package/dist/components/rel-quote-page/rel-quote-page.ts +816 -0
  71. package/dist/components/rel-radio/README.md +120 -0
  72. package/dist/components/rel-radio/rel-radio.ts +41 -73
  73. package/dist/components/rel-resizable/README.md +140 -0
  74. package/dist/components/rel-resizable/index.ts +3 -0
  75. package/dist/components/rel-resizable/rel-resizable-group.ts +374 -0
  76. package/dist/components/rel-resizable/rel-resizable-handle.ts +149 -0
  77. package/dist/components/rel-resizable/rel-resizable-panel.ts +47 -0
  78. package/dist/components/rel-segmented-button/README.md +141 -0
  79. package/dist/components/rel-segmented-button/rel-segmented-button.ts +18 -13
  80. package/dist/components/rel-select/README.md +107 -0
  81. package/dist/components/rel-select/rel-select.ts +14 -14
  82. package/dist/components/rel-sheet/README.md +224 -0
  83. package/dist/components/rel-sheet/rel-sheet.ts +683 -0
  84. package/dist/components/rel-sidebar/README.md +209 -0
  85. package/dist/components/rel-sidebar/rel-sidebar.ts +1158 -0
  86. package/dist/components/rel-slider/README.md +135 -0
  87. package/dist/components/rel-slider/rel-slider.ts +19 -7
  88. package/dist/components/rel-snackbar/README.md +134 -0
  89. package/dist/components/rel-snackbar/rel-snackbar.ts +73 -2
  90. package/dist/components/rel-stepper/README.md +160 -0
  91. package/dist/components/rel-stepper/rel-stepper.ts +29 -8
  92. package/dist/components/rel-switch/README.md +102 -0
  93. package/dist/components/rel-switch/rel-switch.ts +22 -11
  94. package/dist/components/rel-tab/README.md +163 -0
  95. package/dist/components/rel-tab/rel-tab.ts +46 -22
  96. package/dist/components/rel-table/README.md +178 -0
  97. package/dist/components/rel-table/rel-table-body.ts +16 -0
  98. package/dist/components/rel-table/rel-table-caption.ts +22 -0
  99. package/dist/components/rel-table/rel-table-cell.ts +49 -0
  100. package/dist/components/rel-table/rel-table-footer.ts +18 -0
  101. package/dist/components/rel-table/rel-table-head.ts +33 -0
  102. package/dist/components/rel-table/rel-table-header.ts +16 -0
  103. package/dist/components/rel-table/rel-table-row.ts +32 -0
  104. package/dist/components/rel-table/rel-table.ts +47 -0
  105. package/dist/components/rel-textfield/README.md +90 -0
  106. package/dist/components/rel-textfield/rel-textfield.ts +37 -21
  107. package/dist/components/rel-toast/README.md +148 -0
  108. package/dist/components/rel-toast/rel-toast.ts +32 -14
  109. package/dist/components/rel-tooltip/README.md +103 -0
  110. package/dist/components/rel-tooltip/rel-tooltip.ts +9 -9
  111. package/dist/index.d.mts +846 -7
  112. package/dist/index.d.ts +846 -7
  113. package/dist/index.js +10860 -1803
  114. package/dist/index.js.map +1 -1
  115. package/dist/index.mjs +10820 -1809
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/styles/vars.css +293 -183
  118. package/dist/vars-ITL2K3KO.css +294 -0
  119. package/package.json +2 -2
  120. package/dist/components/rel-accordion/rel-accordion.stories.ts +0 -313
  121. package/dist/components/rel-alert/rel-alert.stories.ts +0 -412
  122. package/dist/components/rel-avatar/rel-avatar.stories.ts +0 -327
  123. package/dist/components/rel-badge/rel-badge.stories.ts +0 -350
  124. package/dist/components/rel-breadcrumb/rel-breadcrumb.stories.ts +0 -306
  125. package/dist/components/rel-button/rel-button.stories.ts +0 -356
  126. package/dist/components/rel-card/rel-card.stories.ts +0 -299
  127. package/dist/components/rel-cardmedia/rel-cardmedia.stories.ts +0 -368
  128. package/dist/components/rel-checkbox/rel-checkbox.stories.ts +0 -414
  129. package/dist/components/rel-chip/rel-chip.stories.ts +0 -552
  130. package/dist/components/rel-container/rel-container.stories.ts +0 -239
  131. package/dist/components/rel-divider/rel-divider.stories.ts +0 -229
  132. package/dist/components/rel-layout/rel-layout.stories.ts +0 -713
  133. package/dist/components/rel-menu/rel-menu.stories.ts +0 -910
  134. package/dist/components/rel-progress/rel-progress.stories.ts +0 -817
  135. package/dist/components/rel-radio/rel-radio.stories.ts +0 -1048
  136. package/dist/components/rel-segmented-button/rel-segmented-button.stories.ts +0 -1079
  137. package/dist/components/rel-select/rel-select.stories.ts +0 -1201
  138. package/dist/components/rel-slider/rel-slider.stories.ts +0 -730
  139. package/dist/components/rel-snackbar/rel-snackbar.stories.ts +0 -808
  140. package/dist/components/rel-stepper/rel-stepper.stories.ts +0 -752
  141. package/dist/components/rel-switch/rel-switch.stories.ts +0 -441
  142. package/dist/components/rel-tab/rel-tab.stories.ts +0 -492
  143. package/dist/components/rel-textfield/rel-textfield.stories.ts +0 -710
  144. package/dist/components/rel-toast/rel-toast.stories.ts +0 -394
  145. package/dist/components/rel-tooltip/rel-tooltip.stories.ts +0 -364
@@ -0,0 +1,135 @@
1
+ # rel-slider
2
+
3
+ ## Overview
4
+ A highly customizable range slider component supporting continuous and discrete modes. Features include tick marks, value bubble display, solid/dotted track styles, custom theming via CSS properties, and full accessibility support. Automatically snaps to steps in discrete mode.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Basic continuous slider -->
9
+ <rel-slider value="50" min="0" max="100"></rel-slider>
10
+
11
+ <!-- Discrete slider with ticks -->
12
+ <rel-slider
13
+ type="discrete"
14
+ value="25"
15
+ min="0"
16
+ max="100"
17
+ step="25">
18
+ </rel-slider>
19
+
20
+ <!-- Discrete slider with tick labels -->
21
+ <rel-slider
22
+ type="discrete"
23
+ value="3"
24
+ min="1"
25
+ max="5"
26
+ step="1"
27
+ showTickLabels>
28
+ </rel-slider>
29
+
30
+ <!-- Dotted track without value bubble -->
31
+ <rel-slider
32
+ value="60"
33
+ min="0"
34
+ max="100"
35
+ track="dotted"
36
+ showBubble="false">
37
+ </rel-slider>
38
+
39
+ <!-- Disabled slider -->
40
+ <rel-slider value="30" disabled></rel-slider>
41
+
42
+ <!-- Listen for value changes -->
43
+ <rel-slider id="volumeSlider" value="75" min="0" max="100"></rel-slider>
44
+ <script>
45
+ const slider = document.getElementById('volumeSlider');
46
+ slider.addEventListener('valueChange', (e) => {
47
+ console.log('New value:', e.detail.value);
48
+ });
49
+ </script>
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### Attributes/Properties
55
+ | Name | Type | Default | Description |
56
+ |------|------|---------|-------------|
57
+ | `type` | `"continuous" \| "discrete"` | `"continuous"` | Slider mode: continuous allows any value, discrete snaps to steps |
58
+ | `min` | `number` | `0` | Minimum value |
59
+ | `max` | `number` | `100` | Maximum value |
60
+ | `step` | `number` | `1` | Step increment (used in discrete mode for snapping and ticks) |
61
+ | `value` | `number` | `0` | Current slider value |
62
+ | `disabled` | `boolean` | `false` | Disables the slider |
63
+ | `track` | `"solid" \| "dotted"` | `"solid"` | Visual style of the active track |
64
+ | `showTickLabels` | `boolean` | `false` | Show numeric labels at each tick (discrete mode only) |
65
+ | `showBubble` | `boolean` | `true` | Show value bubble marker above the thumb |
66
+
67
+ ## Events
68
+ | Event | Detail | Description |
69
+ |-------|--------|-------------|
70
+ | `valueChange` | `{ value: number }` | Fired when the slider value changes through user interaction |
71
+
72
+ ## Slots
73
+ Default slot not used.
74
+
75
+ ## CSS Parts
76
+ None exposed.
77
+
78
+ ## Tokens / CSS Variables
79
+
80
+ ### Component-Level Custom Properties
81
+ The component defines these CSS custom properties on `:host` which can be overridden:
82
+
83
+ - `--track-height` - Height of the slider track (default: `5px`)
84
+ - `--thumb-size` - Diameter of the thumb (default: `10px`)
85
+ - `--thumb-stroke` - Thickness of focus/active halo around thumb (default: `7px`)
86
+ - `--thumb-halo-color` - Color of thumb halo (default: `--rel-border-default`)
87
+ - `--tick-size` - Diameter of tick marks (default: `4px`)
88
+ - `--shadow` - Thumb drop shadow (default: `0 2px 4px rgba(0,0,0,0.25)`)
89
+ - `--halo` - Additional halo shadow (default: `0 2px 0 var(--rel-surface-surface), 0 6px 10px rgba(0,0,0,0.07)`)
90
+ - `--marker-width` - Width of value bubble (default: `24px`)
91
+ - `--marker-height` - Height of value bubble (default: `28px`)
92
+
93
+ ### Design Token References
94
+ - `--rel-fontFamilies-primary` - Font family
95
+ - `--rel-colors-gray-border` - Inactive track color
96
+ - `--rel-colors-black` - Active track and thumb color
97
+ - `--rel-colors-white` - Used in dotted track and tick marks
98
+ - `--rel-colors-gray-primary` - Tick mark color (inactive)
99
+ - `--rel-colors-gray-heading` - Tick label color
100
+ - `--rel-colors-gray-placeholder` - Disabled active track and tick colors
101
+ - `--rel-border-default` - Default thumb halo color
102
+ - `--rel-surface-surface` - Disabled track background, used in dotted pattern
103
+ - `--rel-fontSizes-xs` - Tick label font size
104
+
105
+ ## Accessibility
106
+ - Uses native `<input type="range">` for full keyboard and screen reader support
107
+ - Native input is transparent overlay, custom visuals beneath are purely decorative
108
+ - Focus visible state shows halo around custom thumb
109
+ - Disabled state prevents interaction with styled cursor and reduced contrast
110
+ - Respects `prefers-reduced-motion` media query (disables transitions)
111
+
112
+ ### Keyboard Interactions
113
+ - `Arrow Left/Down` - Decrease value
114
+ - `Arrow Right/Up` - Increase value
115
+ - `Home` - Jump to minimum value
116
+ - `End` - Jump to maximum value
117
+ - `Page Up/Down` - Larger increments (browser-dependent)
118
+
119
+ ### Focus Behavior
120
+ - Focus shows halo around custom thumb using `--thumb-halo-color`
121
+ - Active (mouse down) state also shows the halo
122
+
123
+ ## Notes / Edge Cases
124
+ - In **discrete mode**, the slider automatically snaps to the nearest step value as the user drags
125
+ - Tick marks are generated automatically in discrete mode based on `min`, `max`, and `step`
126
+ - If the range doesn't divide evenly by step, a final tick is added at `max`
127
+ - Ticks change color (become white) when the value passes them (active state)
128
+ - **showTickLabels** only has effect in discrete mode
129
+ - **showBubble** displays a pin-drop shaped SVG marker with the current value as text
130
+ - The value bubble uses the "Poppins" font (you may need to load this separately or it will fall back)
131
+ - **Dotted track** uses a `radial-gradient` pattern with white dots over the active color
132
+ - The component has a fixed height of `60px` to accommodate the value bubble
133
+ - When disabled, all interactive colors become muted gray tones
134
+ - Active track width updates dynamically based on the percentage value
135
+ - The component respects `prefers-reduced-motion` and disables all transitions when requested
@@ -31,15 +31,15 @@ export class RelSlider extends LitElement {
31
31
  --track-height: 5px;
32
32
  --thumb-size: 10px;
33
33
  --thumb-stroke: 7px;
34
- --thumb-halo-color: rgba(224, 222, 222, 0.8);
34
+ --thumb-halo-color: var(--rel-border-default);
35
35
  --tick-size: 4px;
36
36
  --shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
37
- --halo: 0 2px 0 #e9e9e9, 0 6px 10px rgba(0, 0, 0, 0.07);
37
+ --halo: 0 2px 0 var(--rel-surface-surface), 0 6px 10px rgba(0, 0, 0, 0.07);
38
38
  --marker-width: 24px;
39
39
  --marker-height: 28px;
40
40
 
41
41
  display: block;
42
- font-family: var(--rel-fontFamilies-primary);
42
+ font-family: var(--rel-fontFamilies-primary, sans-serif);
43
43
  }
44
44
 
45
45
  .rel-slider {
@@ -131,6 +131,18 @@ export class RelSlider extends LitElement {
131
131
  cursor: pointer;
132
132
  }
133
133
 
134
+ .slider-input:focus-visible ~ .thumb-container .custom-thumb {
135
+ box-shadow: 0 0 0 var(--thumb-stroke) var(--thumb-halo-color),
136
+ var(--shadow), var(--halo);
137
+ }
138
+
139
+ @media (prefers-reduced-motion: reduce) {
140
+ .custom-thumb,
141
+ .tick {
142
+ transition: none;
143
+ }
144
+ }
145
+
134
146
  /* Custom Thumb Container */
135
147
  .thumb-container {
136
148
  position: absolute;
@@ -225,7 +237,7 @@ export class RelSlider extends LitElement {
225
237
  .rel-slider.disabled .track-active.dotted {
226
238
  background: radial-gradient(
227
239
  circle,
228
- #eaeaea 0 1px,
240
+ var(--rel-surface-surface) 0 1px,
229
241
  transparent 1px
230
242
  )
231
243
  center/12px 4px repeat-x,
@@ -246,7 +258,7 @@ export class RelSlider extends LitElement {
246
258
 
247
259
  .rel-slider.disabled .custom-thumb {
248
260
  background: var(--rel-colors-gray-placeholder);
249
- box-shadow: 0 0 0 var(--thumb-stroke) #f5f5f5;
261
+ box-shadow: 0 0 0 var(--thumb-stroke) var(--rel-surface-surface);
250
262
  }
251
263
 
252
264
  .rel-slider.disabled .value-marker svg path {
@@ -347,12 +359,12 @@ export class RelSlider extends LitElement {
347
359
  <svg viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg">
348
360
  <path
349
361
  d="M12 0C18.6274 0 24 5.37258 24 12C24 21 12 32 12 32C12 32 0 21 0 12C0 5.37258 5.37258 0 12 0Z"
350
- fill="black" />
362
+ fill="var(--rel-colors-black)" />
351
363
  <text
352
364
  x="12"
353
365
  y="16"
354
366
  text-anchor="middle"
355
- fill="white"
367
+ fill="var(--rel-colors-white)"
356
368
  font-size="12"
357
369
  font-family="Poppins"
358
370
  font-weight="600">
@@ -0,0 +1,134 @@
1
+ # rel-snackbar
2
+
3
+ ## Overview
4
+ A bottom-anchored notification component for brief messages with optional action buttons. Supports single/double line layouts, configurable auto-dismiss duration, longer action mode (2x duration), and optional close icon. Features slide-up animation respecting user motion preferences.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Basic snackbar -->
9
+ <rel-snackbar message="File uploaded successfully"></rel-snackbar>
10
+
11
+ <!-- With action button -->
12
+ <rel-snackbar
13
+ id="undoSnackbar"
14
+ message="Item deleted"
15
+ action="UNDO">
16
+ </rel-snackbar>
17
+ <script>
18
+ const snackbar = document.getElementById('undoSnackbar');
19
+ snackbar.addEventListener('actionClick', () => {
20
+ console.log('Undo action clicked');
21
+ // Perform undo logic
22
+ });
23
+ </script>
24
+
25
+ <!-- Two-line layout -->
26
+ <rel-snackbar
27
+ message="Your message is too long to fit on a single line, so we'll use two."
28
+ lines="double"
29
+ action="DISMISS">
30
+ </rel-snackbar>
31
+
32
+ <!-- Longer action (2x duration) -->
33
+ <rel-snackbar
34
+ message="Changes saved"
35
+ action="VIEW"
36
+ longerAction>
37
+ </rel-snackbar>
38
+
39
+ <!-- Without close icon -->
40
+ <rel-snackbar
41
+ message="Processing..."
42
+ iconClose="false"
43
+ duration="0">
44
+ </rel-snackbar>
45
+
46
+ <!-- Custom duration (10 seconds) -->
47
+ <rel-snackbar
48
+ message="Important notification"
49
+ duration="10000"
50
+ action="GOT IT">
51
+ </rel-snackbar>
52
+
53
+ <!-- Listen for close event -->
54
+ <rel-snackbar id="notif" message="Update available"></rel-snackbar>
55
+ <script>
56
+ const notif = document.getElementById('notif');
57
+ notif.addEventListener('close', () => {
58
+ console.log('Snackbar closed');
59
+ });
60
+ </script>
61
+ ```
62
+
63
+ ## API
64
+
65
+ ### Attributes/Properties
66
+ | Name | Type | Default | Description |
67
+ |------|------|---------|-------------|
68
+ | `message` | `string` | `"This is a snackbar message"` | Primary message text |
69
+ | `action` | `string` | - | Optional action button label (e.g., "UNDO", "RETRY") |
70
+ | `longerAction` | `boolean` | `false` | If true, doubles the auto-dismiss duration |
71
+ | `iconClose` | `boolean` | `true` | Whether to show the close (✖) icon button |
72
+ | `lines` | `"single" \| "double"` | `"single"` | Layout mode (single-line flex-row, double-line flex-column) |
73
+ | `duration` | `number` | `4000` | Auto-dismiss duration in milliseconds (0 = no auto-dismiss) |
74
+
75
+ ## Events
76
+ | Event | Detail | Description |
77
+ |-------|--------|-------------|
78
+ | `actionClick` | None | Fired when the action button is clicked |
79
+ | `close` | None | Fired when snackbar is closed (via action, close button, or auto-dismiss) |
80
+
81
+ ## Slots
82
+ Default slot not used.
83
+
84
+ ## CSS Parts
85
+ None exposed.
86
+
87
+ ## Tokens / CSS Variables
88
+
89
+ ### Semantic Tokens
90
+ - `--rel-fontFamilies-primary` - Font family
91
+ - `--rel-fontSizes-sm` - Font size
92
+ - `--rel-fontWeights-semibold` - Action button font weight
93
+ - `--rel-lineHeights-lineheight-200` - Message line height
94
+
95
+ ### Spacing Tokens
96
+ - `--rel-spacing-space-2xs` - Action button gap, close button padding
97
+
98
+ ### Color Tokens
99
+ - `--rel-colors-black` - Background color
100
+ - `--rel-colors-white` - Text and focus outline color
101
+ - `--rel-colors-green-secondary` - Action button text color
102
+
103
+ ### Shadow Tokens
104
+ - `--rel-shadows-shadow-300` - Drop shadow
105
+
106
+ ### Border Tokens
107
+ - `--rel-borders-radius-border-radius-200` - Border radius
108
+
109
+ ## Accessibility
110
+ - Snackbars are informational and do not interrupt workflows
111
+ - Close and action buttons have proper focus styles
112
+ - Animation respects `prefers-reduced-motion` media query
113
+
114
+ ### Keyboard Interactions
115
+ - `Tab` - Focus action button or close button
116
+ - `Space/Enter` - Activate focused button
117
+
118
+ ### Focus Behavior
119
+ - Buttons show 2px white outline with 2px offset when focused
120
+ - Border radius applied to maintain visual consistency
121
+
122
+ ## Notes / Edge Cases
123
+ - Snackbar has a minimum width of `280px` and maximum width of `500px`
124
+ - **Single-line mode** (`lines="single"`): message and actions are flex-row with `justify-content: space-between`
125
+ - **Double-line mode** (`lines="double"`): layout switches to flex-column with actions aligned to the right
126
+ - Auto-dismiss timer starts in `connectedCallback()` and resets when `duration` or `longerAction` changes
127
+ - If `longerAction` is true, the effective duration is `duration * 2`
128
+ - Setting `duration="0"` disables auto-dismiss
129
+ - Clicking the action button automatically closes the snackbar after dispatching `actionClick`
130
+ - Clicking the close icon dispatches `close` and hides the snackbar (`visible = false`)
131
+ - When `visible` is false, `hidden` class applies `display: none`
132
+ - The component includes a `slide-up` animation (50px translateY → 0) on appearance
133
+ - Animation disabled when `prefers-reduced-motion: reduce` is set
134
+ - Snackbar is `display: block` by default (should be positioned by parent or global styles)
@@ -2,6 +2,7 @@ import { LitElement, html, css } from "lit";
2
2
  import { customElement, property, state } from "lit/decorators.js";
3
3
 
4
4
  export type SnackbarLines = "single" | "double";
5
+ export type SnackbarType = "default" | "success" | "error" | "warning";
5
6
 
6
7
  @customElement("rel-snackbar")
7
8
  export class RelSnackbar extends LitElement {
@@ -17,6 +18,8 @@ export class RelSnackbar extends LitElement {
17
18
 
18
19
  @property({ type: Number }) duration: number = 4000;
19
20
 
21
+ @property({ type: String }) type: SnackbarType = "default";
22
+
20
23
  @state() private visible: boolean = true;
21
24
 
22
25
  private timeout: number | null = null;
@@ -41,6 +44,7 @@ export class RelSnackbar extends LitElement {
41
44
  font-family: var(--rel-fontFamilies-primary);
42
45
  box-shadow: var(--rel-shadows-shadow-300);
43
46
  animation: slide-up 0.3s ease-out;
47
+ border-left: 4px solid transparent;
44
48
  }
45
49
 
46
50
  .snackbar.two-line {
@@ -52,6 +56,34 @@ export class RelSnackbar extends LitElement {
52
56
  display: none;
53
57
  }
54
58
 
59
+ /* Type variants */
60
+ .snackbar.type-success {
61
+ border-left-color: var(--rel-colors-green-secondary, #4ade80);
62
+ }
63
+
64
+ .snackbar.type-error {
65
+ border-left-color: var(--rel-colors-red-primary, #f87171);
66
+ }
67
+
68
+ .snackbar.type-warning {
69
+ border-left-color: var(--rel-colors-amber-primary, #fbbf24);
70
+ }
71
+
72
+ .snackbar-icon {
73
+ display: flex;
74
+ align-items: center;
75
+ margin-right: 10px;
76
+ flex-shrink: 0;
77
+ font-size: 14px;
78
+ }
79
+
80
+ .snackbar-body {
81
+ display: flex;
82
+ align-items: center;
83
+ flex: 1;
84
+ min-width: 0;
85
+ }
86
+
55
87
  .snackbar-message {
56
88
  font-size: var(--rel-fontSizes-sm);
57
89
  line-height: var(--rel-lineHeights-lineheight-200);
@@ -97,10 +129,16 @@ export class RelSnackbar extends LitElement {
97
129
  opacity: 0.6;
98
130
  }
99
131
 
132
+ .snackbar-action:focus-visible {
133
+ outline: 2px solid var(--rel-colors-white, #fff);
134
+ outline-offset: 2px;
135
+ border-radius: 2px;
136
+ }
137
+
100
138
  .snackbar-close {
101
139
  background: none;
102
140
  border: none;
103
- color: var(--rel-colors-white);
141
+ color: var(--rel-colors-white, #fff);
104
142
  cursor: pointer;
105
143
  font-size: 16px;
106
144
  padding: 0;
@@ -120,6 +158,18 @@ export class RelSnackbar extends LitElement {
120
158
  opacity: 0.6;
121
159
  }
122
160
 
161
+ .snackbar-close:focus-visible {
162
+ outline: 2px solid var(--rel-colors-white, #fff);
163
+ outline-offset: 2px;
164
+ border-radius: 2px;
165
+ }
166
+
167
+ @media (prefers-reduced-motion: reduce) {
168
+ .snackbar {
169
+ animation: none;
170
+ }
171
+ }
172
+
123
173
  @keyframes slide-up {
124
174
  from {
125
175
  transform: translateY(50px);
@@ -137,6 +187,12 @@ export class RelSnackbar extends LitElement {
137
187
  this.setAutoDismiss();
138
188
  }
139
189
 
190
+ updated(changed: Map<string, unknown>) {
191
+ if (changed.has("duration") || changed.has("longerAction")) {
192
+ this.setAutoDismiss();
193
+ }
194
+ }
195
+
140
196
  disconnectedCallback() {
141
197
  super.disconnectedCallback();
142
198
  this.clearTimeout();
@@ -177,18 +233,33 @@ export class RelSnackbar extends LitElement {
177
233
  );
178
234
  }
179
235
 
236
+ private getIcon(): string {
237
+ switch (this.type) {
238
+ case "success": return "✓";
239
+ case "error": return "✕";
240
+ case "warning": return "⚠";
241
+ default: return "";
242
+ }
243
+ }
244
+
180
245
  render() {
181
246
  const snackbarClasses = [
182
247
  "snackbar",
183
248
  this.lines === "double" ? "two-line" : "",
184
249
  !this.visible ? "hidden" : "",
250
+ this.type !== "default" ? `type-${this.type}` : "",
185
251
  ]
186
252
  .filter(Boolean)
187
253
  .join(" ");
188
254
 
255
+ const icon = this.getIcon();
256
+
189
257
  return html`
190
258
  <div class="${snackbarClasses}">
191
- <div class="snackbar-message">${this.message}</div>
259
+ <div class="snackbar-body">
260
+ ${icon ? html`<span class="snackbar-icon">${icon}</span>` : ""}
261
+ <div class="snackbar-message">${this.message}</div>
262
+ </div>
192
263
 
193
264
  <div class="snackbar-actions">
194
265
  ${this.action
@@ -0,0 +1,160 @@
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-fontFamilies-primary` - Font family
100
+ - `--rel-fontSizes-sm` - Label font size
101
+ - `--rel-fontWeights-medium` - Default label font weight
102
+ - `--rel-fontWeights-semibold` - Active/done label font weight
103
+
104
+ ### Spacing Tokens
105
+ - `--rel-spacing-space-2xs` - Gap between indicators and labels (text-right mode)
106
+
107
+ ### Color Tokens
108
+ - `--rel-colors-white` - Indicator background (progress, disabled states)
109
+ - `--rel-colors-black` - Active/done indicator background, text, and connector color
110
+ - `--rel-colors-gray-border` - Disabled indicator border and inactive connector
111
+ - `--rel-colors-gray-light` - Disabled indicator background
112
+ - `--rel-text-disabled` - Disabled label text color
113
+ - `--rel-text-primary` - 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%`