@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.
- package/dist/components/rel-accordion/README.md +132 -0
- package/dist/components/rel-accordion/rel-accordion.ts +61 -29
- package/dist/components/rel-alert/README.md +141 -0
- package/dist/components/rel-alert/rel-alert.ts +110 -67
- package/dist/components/rel-avatar/README.md +119 -0
- package/dist/components/rel-avatar/rel-avatar.ts +8 -15
- package/dist/components/rel-badge/README.md +86 -0
- package/dist/components/rel-badge/rel-badge.ts +28 -21
- package/dist/components/rel-breadcrumb/README.md +102 -0
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +24 -18
- package/dist/components/rel-button/README.md +130 -0
- package/dist/components/rel-button/rel-button.ts +39 -59
- package/dist/components/rel-calendar/README.md +109 -0
- package/dist/components/rel-calendar/index.ts +1 -0
- package/dist/components/rel-calendar/rel-calendar.ts +467 -0
- package/dist/components/rel-card/README.md +94 -0
- package/dist/components/rel-card/rel-card.ts +21 -11
- package/dist/components/rel-cardmedia/README.md +127 -0
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +22 -18
- package/dist/components/rel-carousel/README.md +166 -0
- package/dist/components/rel-carousel/index.ts +1 -0
- package/dist/components/rel-carousel/rel-carousel.ts +469 -0
- package/dist/components/rel-chart/README.md +286 -0
- package/dist/components/rel-chart/index.ts +1 -0
- package/dist/components/rel-chart/rel-chart.ts +736 -0
- package/dist/components/rel-checkbox/README.md +77 -0
- package/dist/components/rel-checkbox/rel-checkbox.ts +36 -45
- package/dist/components/rel-chip/README.md +114 -0
- package/dist/components/rel-chip/rel-chip.ts +47 -122
- package/dist/components/rel-container/README.md +99 -0
- package/dist/components/rel-container/rel-container.ts +1 -6
- package/dist/components/rel-date-picker/README.md +253 -0
- package/dist/components/rel-date-picker/index.ts +1 -0
- package/dist/components/rel-date-picker/rel-date-picker.ts +916 -0
- package/dist/components/rel-divider/README.md +100 -0
- package/dist/components/rel-divider/rel-divider.ts +37 -37
- package/dist/components/rel-drawer/README.md +200 -0
- package/dist/components/rel-drawer/index.ts +1 -0
- package/dist/components/rel-drawer/rel-drawer.ts +621 -0
- package/dist/components/rel-kbd/README.md +151 -0
- package/dist/components/rel-kbd/rel-kbd.ts +118 -0
- package/dist/components/rel-layout/README.md +88 -0
- package/dist/components/rel-layout/rel-layout.ts +12 -14
- package/dist/components/rel-menu/README.md +151 -0
- package/dist/components/rel-menu/rel-menu.ts +18 -10
- package/dist/components/rel-menubar/README.md +329 -0
- package/dist/components/rel-menubar/index.ts +2 -0
- package/dist/components/rel-menubar/rel-menubar-menu.ts +16 -0
- package/dist/components/rel-menubar/rel-menubar.ts +576 -0
- package/dist/components/rel-nav-menu/README.md +289 -0
- package/dist/components/rel-nav-menu/index.ts +3 -0
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +143 -0
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +53 -0
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +331 -0
- package/dist/components/rel-navbar/README.md +126 -0
- package/dist/components/rel-navbar/rel-navbar.ts +91 -0
- package/dist/components/rel-otp/README.md +440 -0
- package/dist/components/rel-otp/index.ts +1 -0
- package/dist/components/rel-otp/rel-otp.ts +504 -0
- package/dist/components/rel-pagination/README.md +410 -0
- package/dist/components/rel-pagination/index.ts +1 -0
- package/dist/components/rel-pagination/rel-pagination.ts +376 -0
- package/dist/components/rel-popover/README.md +568 -0
- package/dist/components/rel-popover/index.ts +2 -0
- package/dist/components/rel-popover/rel-popover-content.ts +55 -0
- package/dist/components/rel-popover/rel-popover.ts +327 -0
- package/dist/components/rel-progress/README.md +110 -0
- package/dist/components/rel-progress/rel-progress.ts +58 -20
- package/dist/components/rel-quote-page/README.md +166 -0
- package/dist/components/rel-quote-page/rel-quote-page.ts +816 -0
- package/dist/components/rel-radio/README.md +120 -0
- package/dist/components/rel-radio/rel-radio.ts +41 -73
- package/dist/components/rel-resizable/README.md +140 -0
- package/dist/components/rel-resizable/index.ts +3 -0
- package/dist/components/rel-resizable/rel-resizable-group.ts +374 -0
- package/dist/components/rel-resizable/rel-resizable-handle.ts +149 -0
- package/dist/components/rel-resizable/rel-resizable-panel.ts +47 -0
- package/dist/components/rel-segmented-button/README.md +141 -0
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +18 -13
- package/dist/components/rel-select/README.md +107 -0
- package/dist/components/rel-select/rel-select.ts +14 -14
- package/dist/components/rel-sheet/README.md +224 -0
- package/dist/components/rel-sheet/rel-sheet.ts +683 -0
- package/dist/components/rel-sidebar/README.md +209 -0
- package/dist/components/rel-sidebar/rel-sidebar.ts +1158 -0
- package/dist/components/rel-slider/README.md +135 -0
- package/dist/components/rel-slider/rel-slider.ts +19 -7
- package/dist/components/rel-snackbar/README.md +134 -0
- package/dist/components/rel-snackbar/rel-snackbar.ts +73 -2
- package/dist/components/rel-stepper/README.md +160 -0
- package/dist/components/rel-stepper/rel-stepper.ts +29 -8
- package/dist/components/rel-switch/README.md +102 -0
- package/dist/components/rel-switch/rel-switch.ts +22 -11
- package/dist/components/rel-tab/README.md +163 -0
- package/dist/components/rel-tab/rel-tab.ts +46 -22
- package/dist/components/rel-table/README.md +178 -0
- package/dist/components/rel-table/rel-table-body.ts +16 -0
- package/dist/components/rel-table/rel-table-caption.ts +22 -0
- package/dist/components/rel-table/rel-table-cell.ts +49 -0
- package/dist/components/rel-table/rel-table-footer.ts +18 -0
- package/dist/components/rel-table/rel-table-head.ts +33 -0
- package/dist/components/rel-table/rel-table-header.ts +16 -0
- package/dist/components/rel-table/rel-table-row.ts +32 -0
- package/dist/components/rel-table/rel-table.ts +47 -0
- package/dist/components/rel-textfield/README.md +90 -0
- package/dist/components/rel-textfield/rel-textfield.ts +37 -21
- package/dist/components/rel-toast/README.md +148 -0
- package/dist/components/rel-toast/rel-toast.ts +32 -14
- package/dist/components/rel-tooltip/README.md +103 -0
- package/dist/components/rel-tooltip/rel-tooltip.ts +9 -9
- package/dist/index.d.mts +846 -7
- package/dist/index.d.ts +846 -7
- package/dist/index.js +10860 -1803
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10820 -1809
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +293 -183
- package/dist/vars-ITL2K3KO.css +294 -0
- package/package.json +2 -2
- package/dist/components/rel-accordion/rel-accordion.stories.ts +0 -313
- package/dist/components/rel-alert/rel-alert.stories.ts +0 -412
- package/dist/components/rel-avatar/rel-avatar.stories.ts +0 -327
- package/dist/components/rel-badge/rel-badge.stories.ts +0 -350
- package/dist/components/rel-breadcrumb/rel-breadcrumb.stories.ts +0 -306
- package/dist/components/rel-button/rel-button.stories.ts +0 -356
- package/dist/components/rel-card/rel-card.stories.ts +0 -299
- package/dist/components/rel-cardmedia/rel-cardmedia.stories.ts +0 -368
- package/dist/components/rel-checkbox/rel-checkbox.stories.ts +0 -414
- package/dist/components/rel-chip/rel-chip.stories.ts +0 -552
- package/dist/components/rel-container/rel-container.stories.ts +0 -239
- package/dist/components/rel-divider/rel-divider.stories.ts +0 -229
- package/dist/components/rel-layout/rel-layout.stories.ts +0 -713
- package/dist/components/rel-menu/rel-menu.stories.ts +0 -910
- package/dist/components/rel-progress/rel-progress.stories.ts +0 -817
- package/dist/components/rel-radio/rel-radio.stories.ts +0 -1048
- package/dist/components/rel-segmented-button/rel-segmented-button.stories.ts +0 -1079
- package/dist/components/rel-select/rel-select.stories.ts +0 -1201
- package/dist/components/rel-slider/rel-slider.stories.ts +0 -730
- package/dist/components/rel-snackbar/rel-snackbar.stories.ts +0 -808
- package/dist/components/rel-stepper/rel-stepper.stories.ts +0 -752
- package/dist/components/rel-switch/rel-switch.stories.ts +0 -441
- package/dist/components/rel-tab/rel-tab.stories.ts +0 -492
- package/dist/components/rel-textfield/rel-textfield.stories.ts +0 -710
- package/dist/components/rel-toast/rel-toast.stories.ts +0 -394
- 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:
|
|
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
|
|
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
|
-
|
|
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)
|
|
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-
|
|
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%`
|