fix(slider): normalize value, reactive trackEl, aria-valuetext

This commit is contained in:
Ilia Mashkov
2026-06-02 11:01:08 +03:00
parent 9d6220d2ec
commit d7decd7a00
+17 -1
View File
@@ -87,7 +87,7 @@ const percent = $derived.by(() => {
return Math.min(Math.max(((value - min) / (max - min)) * 100, 0), 100); return Math.min(Math.max(((value - min) / (max - min)) * 100, 0), 100);
}); });
let trackEl: HTMLElement | undefined; let trackEl: HTMLElement | undefined = $state();
let dragging = $state(false); let dragging = $state(false);
/** /**
@@ -101,6 +101,20 @@ function commit(raw: number): void {
} }
} }
/**
* Keep an externally-supplied value normalized to the step grid and range.
* Mirrors the bits-ui primitive's behavior so out-of-range or off-grid
* props don't desync the thumb position from aria-valuenow / the label.
* Converges in one pass: once snapped, the value equals its own snap.
*/
$effect(() => {
const normalized = snapToStep(value, { min, max, step });
if (normalized !== value) {
value = normalized;
onValueChange?.(normalized);
}
});
/** /**
* Resolve a pointer event to a value using the live track rect. * Resolve a pointer event to a value using the live track rect.
*/ */
@@ -229,6 +243,7 @@ const thumbClasses = `block w-2.5 h-2.5 bg-brand
aria-valuemin={min} aria-valuemin={min}
aria-valuemax={max} aria-valuemax={max}
aria-valuenow={value} aria-valuenow={value}
aria-valuetext={String(format(value))}
aria-disabled={disabled ? 'true' : undefined} aria-disabled={disabled ? 'true' : undefined}
data-active={dragging ? '' : undefined} data-active={dragging ? '' : undefined}
onkeydown={handleKeyDown} onkeydown={handleKeyDown}
@@ -276,6 +291,7 @@ const thumbClasses = `block w-2.5 h-2.5 bg-brand
aria-valuemin={min} aria-valuemin={min}
aria-valuemax={max} aria-valuemax={max}
aria-valuenow={value} aria-valuenow={value}
aria-valuetext={String(format(value))}
aria-disabled={disabled ? 'true' : undefined} aria-disabled={disabled ? 'true' : undefined}
data-active={dragging ? '' : undefined} data-active={dragging ? '' : undefined}
onkeydown={handleKeyDown} onkeydown={handleKeyDown}