@reliability-design/web 1.3.1 → 1.4.0

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 (123) hide show
  1. package/dist/components/rel-accordion/README.md +13 -13
  2. package/dist/components/rel-accordion/rel-accordion.ts +80 -45
  3. package/dist/components/rel-alert/README.md +15 -15
  4. package/dist/components/rel-alert/rel-alert.ts +153 -158
  5. package/dist/components/rel-avatar/README.md +15 -15
  6. package/dist/components/rel-avatar/rel-avatar.ts +42 -38
  7. package/dist/components/rel-badge/README.md +5 -5
  8. package/dist/components/rel-badge/rel-badge.ts +46 -11
  9. package/dist/components/rel-breadcrumb/README.md +7 -7
  10. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +16 -13
  11. package/dist/components/rel-button/README.md +20 -20
  12. package/dist/components/rel-button/rel-button.ts +292 -105
  13. package/dist/components/rel-calendar/README.md +5 -5
  14. package/dist/components/rel-calendar/rel-calendar.ts +61 -45
  15. package/dist/components/rel-card/README.md +6 -6
  16. package/dist/components/rel-card/rel-card.ts +88 -35
  17. package/dist/components/rel-cardmedia/README.md +9 -9
  18. package/dist/components/rel-cardmedia/rel-cardmedia.ts +27 -20
  19. package/dist/components/rel-carousel/README.md +3 -3
  20. package/dist/components/rel-carousel/rel-carousel.ts +174 -90
  21. package/dist/components/rel-chart/README.md +8 -8
  22. package/dist/components/rel-chart/rel-chart.ts +59 -41
  23. package/dist/components/rel-checkbox/README.md +7 -7
  24. package/dist/components/rel-checkbox/rel-checkbox.ts +61 -61
  25. package/dist/components/rel-chip/README.md +16 -16
  26. package/dist/components/rel-chip/rel-chip.ts +143 -111
  27. package/dist/components/rel-container/README.md +11 -11
  28. package/dist/components/rel-container/rel-container.ts +35 -9
  29. package/dist/components/rel-date-picker/README.md +43 -7
  30. package/dist/components/rel-date-picker/date-format.test.ts +43 -0
  31. package/dist/components/rel-date-picker/date-format.ts +47 -0
  32. package/dist/components/rel-date-picker/rel-date-picker.ts +154 -82
  33. package/dist/components/rel-divider/README.md +9 -9
  34. package/dist/components/rel-divider/rel-divider.ts +10 -9
  35. package/dist/components/rel-drawer/README.md +1 -1
  36. package/dist/components/rel-drawer/rel-drawer-footer.ts +1 -1
  37. package/dist/components/rel-drawer/rel-drawer.ts +56 -28
  38. package/dist/components/rel-kbd/README.md +20 -20
  39. package/dist/components/rel-kbd/rel-kbd.ts +119 -25
  40. package/dist/components/rel-layout/README.md +1 -1
  41. package/dist/components/rel-layout/rel-layout.ts +2 -2
  42. package/dist/components/rel-menu/README.md +15 -15
  43. package/dist/components/rel-menu/rel-menu.ts +155 -88
  44. package/dist/components/rel-menubar/README.md +20 -20
  45. package/dist/components/rel-menubar/rel-menubar.ts +47 -31
  46. package/dist/components/rel-nav-menu/README.md +21 -21
  47. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +17 -14
  48. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +33 -14
  49. package/dist/components/rel-nav-menu/rel-nav-menu.ts +14 -7
  50. package/dist/components/rel-navbar/README.md +7 -7
  51. package/dist/components/rel-navbar/rel-navbar.ts +12 -11
  52. package/dist/components/rel-otp/README.md +3 -3
  53. package/dist/components/rel-otp/rel-otp.ts +46 -30
  54. package/dist/components/rel-pagination/README.md +18 -18
  55. package/dist/components/rel-pagination/rel-pagination.ts +141 -90
  56. package/dist/components/rel-popover/README.md +13 -13
  57. package/dist/components/rel-popover/rel-popover-content.ts +39 -14
  58. package/dist/components/rel-popover/rel-popover.ts +18 -7
  59. package/dist/components/rel-progress/README.md +5 -5
  60. package/dist/components/rel-progress/rel-progress.ts +16 -12
  61. package/dist/components/rel-radio/README.md +9 -9
  62. package/dist/components/rel-radio/rel-radio.ts +64 -50
  63. package/dist/components/rel-range-picker/rel-range-picker.ts +120 -117
  64. package/dist/components/rel-resizable/README.md +4 -4
  65. package/dist/components/rel-resizable/rel-resizable-group.ts +15 -4
  66. package/dist/components/rel-resizable/rel-resizable-handle.ts +13 -9
  67. package/dist/components/rel-resizable/rel-resizable-panel.ts +11 -0
  68. package/dist/components/rel-segmented-button/README.md +10 -10
  69. package/dist/components/rel-segmented-button/rel-segmented-button.ts +39 -40
  70. package/dist/components/rel-select/README.md +14 -14
  71. package/dist/components/rel-select/rel-select.ts +120 -188
  72. package/dist/components/rel-sheet/README.md +10 -10
  73. package/dist/components/rel-sheet/rel-sheet.ts +82 -23
  74. package/dist/components/rel-sidebar/README.md +5 -5
  75. package/dist/components/rel-sidebar/rel-sidebar.ts +75 -60
  76. package/dist/components/rel-skeleton/rel-skeleton.ts +8 -13
  77. package/dist/components/rel-slider/README.md +10 -10
  78. package/dist/components/rel-slider/rel-slider.ts +230 -57
  79. package/dist/components/rel-snackbar/README.md +9 -9
  80. package/dist/components/rel-snackbar/rel-snackbar.ts +44 -32
  81. package/dist/components/rel-stepper/README.md +10 -10
  82. package/dist/components/rel-stepper/rel-stepper.ts +110 -46
  83. package/dist/components/rel-switch/README.md +5 -5
  84. package/dist/components/rel-switch/rel-switch.ts +23 -12
  85. package/dist/components/rel-tab/README.md +13 -13
  86. package/dist/components/rel-tab/rel-tab.ts +63 -19
  87. package/dist/components/rel-table/README.md +7 -7
  88. package/dist/components/rel-table/rel-table-body.ts +2 -1
  89. package/dist/components/rel-table/rel-table-caption.ts +10 -7
  90. package/dist/components/rel-table/rel-table-cell.ts +7 -6
  91. package/dist/components/rel-table/rel-table-footer.ts +4 -3
  92. package/dist/components/rel-table/rel-table-head.ts +11 -9
  93. package/dist/components/rel-table/rel-table-header.ts +2 -1
  94. package/dist/components/rel-table/rel-table-row.ts +5 -4
  95. package/dist/components/rel-table/rel-table.ts +16 -7
  96. package/dist/components/rel-textfield/README.md +11 -11
  97. package/dist/components/rel-textfield/rel-textfield.ts +172 -91
  98. package/dist/components/rel-toast/README.md +11 -11
  99. package/dist/components/rel-toast/rel-toast.ts +33 -30
  100. package/dist/components/rel-tooltip/README.md +7 -7
  101. package/dist/components/rel-tooltip/rel-tooltip.ts +160 -123
  102. package/dist/components/rel-topbar/rel-topbar-actions.ts +1 -2
  103. package/dist/components/rel-topbar/rel-topbar-brand.ts +8 -5
  104. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +10 -8
  105. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +4 -5
  106. package/dist/components/rel-topbar/rel-topbar-item.ts +23 -22
  107. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -1
  108. package/dist/components/rel-topbar/rel-topbar-profile.ts +68 -50
  109. package/dist/components/rel-topbar/rel-topbar-utilities.ts +1 -2
  110. package/dist/components/rel-topbar/rel-topbar.ts +31 -29
  111. package/dist/index.d.mts +151 -39
  112. package/dist/index.d.ts +151 -39
  113. package/dist/index.js +3544 -2289
  114. package/dist/index.js.map +1 -1
  115. package/dist/index.mjs +3876 -2622
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/styles/vars.css +653 -363
  118. package/dist/vars-WY2XCF5G.css +653 -0
  119. package/package.json +3 -2
  120. package/dist/components/rel-range-picker/rel-range-picker.css +0 -349
  121. package/dist/styles/vars-v2.css +0 -525
  122. package/dist/vars-F54UGCHM.css +0 -363
  123. package/dist/vars-v2-VMGWTFJZ.css +0 -525
@@ -1,13 +1,19 @@
1
1
  import { LitElement, html, css } from "lit";
2
2
  import { customElement, property, state } from "lit/decorators.js";
3
- import "../../styles/vars-v2.css";
4
3
 
5
- export type SliderType = "continuous" | "discrete";
4
+ /**
5
+ * "continuous"/"discrete" are the legacy tick-mode values; Figma's Type axis
6
+ * adds "default" (alias of continuous) and "range" (dual-thumb interval).
7
+ */
8
+ export type SliderType = "continuous" | "discrete" | "default" | "range";
6
9
  export type TrackStyle = "solid" | "dotted";
7
10
 
8
11
  @customElement("rel-slider")
9
12
  export class RelSlider extends LitElement {
10
- @property({ type: String }) type: SliderType = "continuous";
13
+ @property({ type: String, reflect: true }) type: SliderType = "continuous";
14
+
15
+ /** Figma Size axis (S/M/L): scales track, thumb and ticks. */
16
+ @property({ type: String, reflect: true }) size: "sm" | "md" | "lg" = "md";
11
17
 
12
18
  @property({ type: Number }) min: number = 0;
13
19
 
@@ -21,10 +27,13 @@ export class RelSlider extends LitElement {
21
27
 
22
28
  @property({ type: Boolean }) showTickLabels: boolean = false;
23
29
 
24
- @property({ type: Boolean }) showBubble: boolean = true;
30
+ @property({ type: Boolean }) showBubble: boolean = true;
25
31
 
26
32
  @property({ type: Number }) value: number = 0;
27
33
 
34
+ /** Upper value when type="range" (attribute value-end). */
35
+ @property({ type: Number, attribute: "value-end" }) valueEnd: number = 100;
36
+
28
37
  @state() private ticks: number[] = [];
29
38
 
30
39
  private _onChange: (value: number) => void = () => {};
@@ -32,18 +41,42 @@ export class RelSlider extends LitElement {
32
41
 
33
42
  static styles = css`
34
43
  :host {
35
- --track-height: 5px;
36
- --thumb-size: 10px;
44
+ color: var(--rel-text-default);
45
+ --track-height: 8px;
46
+ --thumb-size: 20px;
37
47
  --thumb-stroke: 7px;
38
- --thumb-halo-color: var(--rel-color-border-default);
48
+ --thumb-halo-color: var(--rel-border-default);
39
49
  --tick-size: 4px;
40
50
  --shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
41
- --halo: 0 2px 0 var(--rel-color-bg-tertiary), 0 6px 10px rgba(0, 0, 0, 0.07);
51
+ --halo: 0 2px 0 var(--rel-bg-neutral-elevated-1), 0 6px 10px rgba(0, 0, 0, 0.07);
42
52
  --marker-width: 24px;
43
53
  --marker-height: 28px;
44
54
 
45
55
  display: block;
46
- font-family: var(--rel-fontFamilies-primary);
56
+ font-family: var(--rel-label-md-font-family);
57
+ font-weight: var(--rel-label-md-font-weight);
58
+ font-size: var(--rel-label-md-font-size);
59
+ line-height: var(--rel-label-md-line-height);
60
+ letter-spacing: var(--rel-label-md-letter-spacing);
61
+ }
62
+
63
+ /* Figma Size axis: S = 6px track / 16px thumb · M = 8/20 · L = 10/24 */
64
+ :host([size="sm"]) {
65
+ --track-height: 6px;
66
+ --thumb-size: 16px;
67
+ --tick-size: 4px;
68
+ }
69
+
70
+ :host([size="md"]) {
71
+ --track-height: 8px;
72
+ --thumb-size: 20px;
73
+ --tick-size: 5px;
74
+ }
75
+
76
+ :host([size="lg"]) {
77
+ --track-height: 10px;
78
+ --thumb-size: 24px;
79
+ --tick-size: 6px;
47
80
  }
48
81
 
49
82
  .rel-slider {
@@ -60,7 +93,7 @@ export class RelSlider extends LitElement {
60
93
  left: 0;
61
94
  width: 100%;
62
95
  height: var(--track-height);
63
- background: var(--rel-color-border-default);
96
+ background: var(--rel-bg-neutral-elevated-3);
64
97
  border-radius: 2px;
65
98
  transform: translateY(-50%);
66
99
  pointer-events: none;
@@ -71,7 +104,7 @@ export class RelSlider extends LitElement {
71
104
  top: 50%;
72
105
  left: 0;
73
106
  height: var(--track-height);
74
- background: var(--rel-color-text-primary);
107
+ background: var(--rel-text-default);
75
108
  border-radius: 2px;
76
109
  transform: translateY(-50%);
77
110
  pointer-events: none;
@@ -80,9 +113,19 @@ export class RelSlider extends LitElement {
80
113
  .track-active.dotted {
81
114
  background: radial-gradient(
82
115
  circle,
83
- var(--rel-color-text-primary) 0 2px,
116
+ var(--rel-text-default) 0 2px,
84
117
  transparent 2px
85
- ) 0 50%/12px 5px repeat-x;
118
+ ) 0 50%/var(--rel-spacing-sm) 5px repeat-x;
119
+ }
120
+
121
+ /* Range mode: pointer interaction is handled by the container so each
122
+ thumb can be grabbed; the native inputs stay for keyboard/AT. */
123
+ .rel-slider.range .slider-input {
124
+ pointer-events: none;
125
+ }
126
+
127
+ .rel-slider.range {
128
+ touch-action: none;
86
129
  }
87
130
 
88
131
  /* Input */
@@ -177,7 +220,14 @@ export class RelSlider extends LitElement {
177
220
  .value-marker {
178
221
  width: var(--marker-width);
179
222
  height: var(--marker-height);
180
- margin-bottom: 4px;
223
+ margin-bottom: var(--rel-spacing-3xs);
224
+ }
225
+
226
+ .value-marker text {
227
+ font-family: var(--rel-label-sm-font-family);
228
+ font-weight: var(--rel-label-sm-font-weight);
229
+ font-size: var(--rel-label-sm-font-size);
230
+ line-height: var(--rel-label-sm-line-height);
181
231
  }
182
232
 
183
233
  .value-marker svg {
@@ -190,13 +240,18 @@ export class RelSlider extends LitElement {
190
240
  .custom-thumb {
191
241
  width: var(--thumb-size);
192
242
  height: var(--thumb-size);
193
- background: var(--rel-color-text-primary);
243
+ background: var(--rel-border-strong);
194
244
  border-radius: 50%;
195
245
  transition: box-shadow 0.15s ease;
196
246
  }
197
247
 
248
+ .slider-input:hover:not(:disabled) ~ .thumb-container .custom-thumb {
249
+ box-shadow: 0 0 0 var(--thumb-stroke) var(--rel-action-overlay-hover),
250
+ var(--shadow), var(--halo);
251
+ }
252
+
198
253
  .slider-input:active ~ .thumb-container .custom-thumb {
199
- box-shadow: 0 0 0 var(--thumb-stroke) var(--thumb-halo-color),
254
+ box-shadow: 0 0 0 var(--thumb-stroke) var(--rel-action-overlay-pressed),
200
255
  var(--shadow), var(--halo);
201
256
  }
202
257
 
@@ -214,7 +269,7 @@ export class RelSlider extends LitElement {
214
269
  position: absolute;
215
270
  width: var(--tick-size);
216
271
  height: var(--tick-size);
217
- background: var(--rel-color-text-primary);
272
+ background: var(--rel-text-default);
218
273
  border-radius: 50%;
219
274
  transform: translate(-50%, -50%);
220
275
  transition: background 0.2s;
@@ -222,18 +277,22 @@ export class RelSlider extends LitElement {
222
277
  }
223
278
 
224
279
  .tick.active {
225
- background: var(--rel-color-bg-primary);
280
+ background: var(--rel-bg-neutral);
226
281
  }
227
282
 
228
283
  /* Tick labels */
229
284
  .tick-labels {
230
285
  position: absolute;
231
- top: calc(50% + var(--tick-size) + 6px);
286
+ top: calc(50% + var(--tick-size) + var(--rel-spacing-2xs));
232
287
  left: 0;
233
288
  width: 100%;
234
- font-size: var(--rel-fontSizes-xs);
235
- color: var(--rel-color-text-heading);
289
+ color: var(--rel-text-label);
236
290
  pointer-events: none;
291
+ font-family: var(--rel-label-xs-font-family);
292
+ font-weight: var(--rel-label-xs-font-weight);
293
+ font-size: var(--rel-label-xs-font-size);
294
+ line-height: var(--rel-label-xs-line-height);
295
+ letter-spacing: var(--rel-label-xs-letter-spacing);
237
296
  }
238
297
 
239
298
  .tick-label {
@@ -243,29 +302,29 @@ export class RelSlider extends LitElement {
243
302
 
244
303
  /* Disabled State */
245
304
  .rel-slider.disabled .track {
246
- background: var(--rel-color-border-default);
305
+ background: var(--rel-border-default);
247
306
  }
248
307
 
249
308
  .rel-slider.disabled .track-active {
250
- background: var(--rel-color-text-placeholder);
309
+ background: var(--rel-text-placeholder);
251
310
  }
252
311
 
253
312
  .rel-slider.disabled .track-active.dotted {
254
313
  background: radial-gradient(
255
314
  circle,
256
- var(--rel-color-bg-tertiary) 0 1px,
315
+ var(--rel-bg-neutral-elevated-1) 0 1px,
257
316
  transparent 1px
258
317
  )
259
- center/12px 4px repeat-x,
260
- var(--rel-color-text-placeholder);
318
+ center/var(--rel-spacing-sm) 4px repeat-x,
319
+ var(--rel-text-placeholder);
261
320
  }
262
321
 
263
322
  .rel-slider.disabled .tick {
264
- background: var(--rel-color-text-placeholder);
323
+ background: var(--rel-text-placeholder);
265
324
  }
266
325
 
267
326
  .rel-slider.disabled .tick-label {
268
- color: var(--rel-color-text-placeholder);
327
+ color: var(--rel-text-placeholder);
269
328
  }
270
329
 
271
330
  .rel-slider.disabled .slider-input {
@@ -273,7 +332,7 @@ export class RelSlider extends LitElement {
273
332
  }
274
333
 
275
334
  .rel-slider.disabled .custom-thumb {
276
- background: var(--rel-color-text-placeholder);
335
+ background: var(--rel-text-placeholder);
277
336
  box-shadow: none;
278
337
  }
279
338
 
@@ -283,26 +342,17 @@ export class RelSlider extends LitElement {
283
342
  }
284
343
 
285
344
  .rel-slider.disabled .value-marker svg path {
286
- fill: var(--rel-colors-gray-placeholder);
345
+ fill: var(--rel-text-placeholder);
287
346
  }
288
347
 
289
348
  /* Dark mode overrides */
290
349
  :host-context([data-theme="dark"]),
291
350
  :host-context(.dark) {
292
- --thumb-halo-color: var(--rel-color-border-default);
293
- --halo: 0 2px 0 var(--rel-color-bg-selected),
351
+ --thumb-halo-color: var(--rel-border-default);
352
+ --halo: 0 2px 0 var(--rel-bg-neutral-elevated-2),
294
353
  0 6px 10px rgba(0, 0, 0, 0.3);
295
354
  }
296
355
 
297
- :host-context([data-theme="dark"]) .value-marker svg path,
298
- :host-context(.dark) .value-marker svg path {
299
- fill: #2B2B2B;
300
- }
301
-
302
- :host-context([data-theme="dark"]) .value-marker text,
303
- :host-context(.dark) .value-marker text {
304
- fill: #FFFFFF;
305
- }
306
356
  `;
307
357
 
308
358
  connectedCallback() {
@@ -319,16 +369,94 @@ export class RelSlider extends LitElement {
319
369
  ) {
320
370
  this.setupTicks();
321
371
  }
322
- if (changedProperties.has("value")) {
372
+ if (
373
+ changedProperties.has("value") ||
374
+ changedProperties.has("valueEnd") ||
375
+ changedProperties.has("type")
376
+ ) {
323
377
  this.updateActiveWidth();
324
378
  }
325
379
  }
326
380
 
381
+ private get isRange(): boolean {
382
+ return this.type === "range";
383
+ }
384
+
327
385
  private get percentage(): number {
328
386
  if (this.max === this.min) return 0;
329
387
  return ((this.value - this.min) / (this.max - this.min)) * 100;
330
388
  }
331
389
 
390
+ private get percentageEnd(): number {
391
+ if (this.max === this.min) return 0;
392
+ return ((this.valueEnd - this.min) / (this.max - this.min)) * 100;
393
+ }
394
+
395
+ private dragThumb: "start" | "end" | null = null;
396
+
397
+ private valueFromPointer(e: PointerEvent): number {
398
+ const el = this.shadowRoot?.querySelector(".rel-slider") as HTMLElement;
399
+ if (!el) return this.min;
400
+ const rect = el.getBoundingClientRect();
401
+ const pct = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));
402
+ let v = this.min + pct * (this.max - this.min);
403
+ v = Math.round(v / this.step) * this.step;
404
+ return Math.min(this.max, Math.max(this.min, v));
405
+ }
406
+
407
+ private onRangePointerDown(e: PointerEvent) {
408
+ if (!this.isRange || this.disabled) return;
409
+ const v = this.valueFromPointer(e);
410
+ this.dragThumb =
411
+ Math.abs(v - this.value) <= Math.abs(v - this.valueEnd) ? "start" : "end";
412
+ (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
413
+ this.applyRangeValue(v);
414
+ }
415
+
416
+ private onRangePointerMove(e: PointerEvent) {
417
+ if (!this.dragThumb) return;
418
+ this.applyRangeValue(this.valueFromPointer(e));
419
+ }
420
+
421
+ private onRangePointerUp() {
422
+ this.dragThumb = null;
423
+ }
424
+
425
+ private applyRangeValue(v: number) {
426
+ if (this.dragThumb === "start") {
427
+ this.value = Math.min(v, this.valueEnd);
428
+ } else if (this.dragThumb === "end") {
429
+ this.valueEnd = Math.max(v, this.value);
430
+ }
431
+ this.updateActiveWidth();
432
+ this.emitRangeChange();
433
+ }
434
+
435
+ private emitRangeChange() {
436
+ this.dispatchEvent(
437
+ new CustomEvent("rel-change", {
438
+ detail: { value: this.value, valueEnd: this.valueEnd },
439
+ bubbles: true,
440
+ composed: true,
441
+ })
442
+ );
443
+ this._onChange(this.value);
444
+ }
445
+
446
+ private onRangeInputStart(ev: Event) {
447
+ const next = Number((ev.target as HTMLInputElement).value);
448
+ this.value = Math.min(next, this.valueEnd);
449
+ this.updateActiveWidth();
450
+ this.emitRangeChange();
451
+ }
452
+
453
+ private onRangeInputEnd(ev: Event) {
454
+ const next = Number((ev.target as HTMLInputElement).value);
455
+ this.valueEnd = Math.max(next, this.value);
456
+ this.updateActiveWidth();
457
+ this.emitRangeChange();
458
+ }
459
+
332
460
  private setupTicks() {
333
461
  if (this.type !== "discrete") {
334
462
  this.ticks = [];
@@ -384,40 +512,43 @@ export class RelSlider extends LitElement {
384
512
 
385
513
  private updateActiveWidth() {
386
514
  const activeEl = this.shadowRoot?.querySelector(".track-active") as HTMLDivElement;
387
- if (activeEl) {
388
- if (this.type === "discrete") {
389
- const stepPercent = (this.step / (this.max - this.min)) * 100;
390
- const snappedPct = Math.round(this.percentage / stepPercent) * stepPercent;
391
- activeEl.style.width = `${snappedPct}%`;
392
- } else {
393
- activeEl.style.width = `${this.percentage}%`;
394
- }
515
+ if (!activeEl) return;
516
+
517
+ if (this.isRange) {
518
+ activeEl.style.left = `${this.percentage}%`;
519
+ activeEl.style.width = `${Math.max(0, this.percentageEnd - this.percentage)}%`;
520
+ } else if (this.type === "discrete") {
521
+ const stepPercent = (this.step / (this.max - this.min)) * 100;
522
+ const snappedPct = Math.round(this.percentage / stepPercent) * stepPercent;
523
+ activeEl.style.width = `${snappedPct}%`;
524
+ } else {
525
+ activeEl.style.width = `${this.percentage}%`;
395
526
  }
396
527
  }
397
528
 
398
- private renderThumbContainer() {
529
+ private renderThumbContainer(pct: number = this.percentage, val: number = this.value) {
399
530
  return html`
400
- <div class="thumb-container" style="left: ${this.percentage}%">
531
+ <div class="thumb-container" style="left: ${pct}%">
401
532
  ${this.showBubble ? html`
402
533
  <div class="value-marker">
403
534
  <svg viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg">
404
535
  <path
405
536
  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"
406
- fill="var(--rel-color-text-primary)" />
537
+ fill="var(--rel-bg-neutral-inverse-2)" />
407
538
  <text
408
539
  x="12"
409
540
  y="16"
410
541
  text-anchor="middle"
411
- fill="var(--rel-color-bg-primary)"
542
+ fill="var(--rel-text-inverse)"
412
543
  font-size="12"
413
544
  font-family="Poppins"
414
545
  font-weight="600">
415
- ${this.value}
546
+ ${val}
416
547
  </text>
417
548
  </svg>
418
549
  </div>
419
550
  ` : ""}
420
- <div class="custom-thumb"></div>
551
+ <div part="thumb" class="custom-thumb"></div>
421
552
  </div>
422
553
  `;
423
554
  }
@@ -461,6 +592,7 @@ export class RelSlider extends LitElement {
461
592
  "rel-slider",
462
593
  this.disabled ? "disabled" : "",
463
594
  this.type === "discrete" ? "has-ticks" : "",
595
+ this.isRange ? "range" : "",
464
596
  ]
465
597
  .filter(Boolean)
466
598
  .join(" ");
@@ -472,9 +604,50 @@ export class RelSlider extends LitElement {
472
604
  .filter(Boolean)
473
605
  .join(" ");
474
606
 
607
+ if (this.isRange) {
608
+ return html`
609
+ <div
610
+ class="${sliderClasses}"
611
+ @pointerdown="${this.onRangePointerDown}"
612
+ @pointermove="${this.onRangePointerMove}"
613
+ @pointerup="${this.onRangePointerUp}"
614
+ @pointercancel="${this.onRangePointerUp}"
615
+ >
616
+ <div part="track" class="track"></div>
617
+ <div class="${trackActiveClasses}"></div>
618
+
619
+ <input
620
+ class="slider-input"
621
+ type="range"
622
+ aria-label="Range start"
623
+ .min="${String(this.min)}"
624
+ .max="${String(this.max)}"
625
+ .step="${String(this.step)}"
626
+ .value="${String(this.value)}"
627
+ ?disabled="${this.disabled}"
628
+ @input="${this.onRangeInputStart}"
629
+ @blur="${() => this._onTouched()}" />
630
+ <input
631
+ class="slider-input"
632
+ type="range"
633
+ aria-label="Range end"
634
+ .min="${String(this.min)}"
635
+ .max="${String(this.max)}"
636
+ .step="${String(this.step)}"
637
+ .value="${String(this.valueEnd)}"
638
+ ?disabled="${this.disabled}"
639
+ @input="${this.onRangeInputEnd}"
640
+ @blur="${() => this._onTouched()}" />
641
+
642
+ ${this.renderThumbContainer(this.percentage, this.value)}
643
+ ${this.renderThumbContainer(this.percentageEnd, this.valueEnd)}
644
+ </div>
645
+ `;
646
+ }
647
+
475
648
  return html`
476
649
  <div class="${sliderClasses}">
477
- <div class="track"></div>
650
+ <div part="track" class="track"></div>
478
651
  <div class="${trackActiveClasses}"></div>
479
652
 
480
653
  <input
@@ -87,24 +87,24 @@ None exposed.
87
87
  ## Tokens / CSS Variables
88
88
 
89
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
90
+ - `--rel-fonts-font-family` - Font family
91
+ - `--rel-body-sm-regular-font-size` - Font size
92
+ - `--rel-fonts-weight-body-semibold` - Action button font weight
93
+ - `--rel-body-md-regular-line-height` - Message line height
94
94
 
95
95
  ### Spacing Tokens
96
- - `--rel-spacing-space-2xs` - Action button gap, close button padding
96
+ - `--rel-spacing-2xs` - Action button gap, close button padding
97
97
 
98
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
99
+ - `--rel-text-default` - Background color
100
+ - `--rel-bg-surface` - Text and focus outline color
101
+ - `--rel-bg-success-light` - Action button text color
102
102
 
103
103
  ### Shadow Tokens
104
104
  - `--rel-shadows-shadow-300` - Drop shadow
105
105
 
106
106
  ### Border Tokens
107
- - `--rel-borders-radius-border-radius-200` - Border radius
107
+ - `--rel-border-radius-sm` - Border radius
108
108
 
109
109
  ## Accessibility
110
110
  - Snackbars are informational and do not interrupt workflows