A React slider with a Liquid Glass track, single values, ranges, and vertical orientation.
Slider renders the control, track, indicator, and glass thumb internally. children is intentionally not supported; style merges into the outermost root.
The slider below is the real component. Its label and value are rendered outside the slider; dragging, clicking the track, or using the arrow keys updates the value.
Slider does not render a visible label. Point aria-labelledby at a visible label, or pass aria-label; both are forwarded from the root to every thumb, and aria-describedby is forwarded as well. For range sliders, use getAriaLabel to name each thumb.
aria-invalid and aria-errormessage are applied to the underlying input[type="range"], so validation state supplied by a form library reaches the focusable control. A plain aria-label is shared by every thumb in a range slider; pass getAriaLabel when each thumb needs a distinct name.
Passing an array renders one thumb per value. format follows Intl.NumberFormatOptions and is applied to the thumb's accessible value text.
orientation="vertical" switches the track, indicator, and thumb to a vertical layout:
The disabled state uses the native disabled attribute, stopping both dragging and keyboard interaction:
Slider forwards name and submits the current value through a hidden input[type="range"]:
min, max, and step define the scale. For range sliders, minStepsBetweenValues keeps the thumbs apart, while thumbAlignment and thumbCollisionBehavior control how they meet the edges and each other.
Step 10 with five steps between values keeps a minimum gap of 50.
Thumbs align to the control edges and swap places when they meet.
Each thumb is a slider with aria-valuemin, aria-valuemax, aria-valuenow, and a name from aria-label, aria-labelledby, or getAriaLabel.
Arrow keys change the value by step, and Page Up and Page Down use largeStep. Home and End move a single-value slider to its bounds; on a range slider they move the focused thumb to the adjacent thumb boundary, while the outer thumbs still reach the bounds. Range sliders need a distinct name for every thumb. aria-invalid and aria-errormessage reach the underlying range input. See the accessibility guide for naming examples.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | readonly number[] | — | Controlled value; an array renders one thumb per value. |
defaultValue | number | readonly number[] | — | Uncontrolled initial value. |
onValueChange | (value, details) => void | — | Called when the value changes. |
onValueCommitted | (value, details) => void | — | Called when a value change is committed. |
name | string | — | Field name used when submitting a form. |
form | string | — | Identifies the form that owns the slider inputs. |
min | number | 0 | Minimum value. |
max | number | 100 | Maximum value. |
step | number | 1 | Step for dragging and arrow keys. |
largeStep | number | 10 | Step for Page Up / Page Down and Shift + arrow keys. |
minStepsBetweenValues | number | 0 | Minimum steps between range thumb values. |
orientation | "horizontal" | "vertical" | "horizontal" | Layout and keyboard orientation. |
format | Intl.NumberFormatOptions | — | Value format used by the accessible value text. |
locale | Intl.LocalesArgument | — | Locale used for number formatting. |
getAriaLabel | (index: number) => string | — | Accessible name for the thumb at the given index. Use it for range sliders. |
getAriaValueText | (formattedValue, value, index) => string | — | Custom accessible value text for each thumb. |
aria-label | string | — | Accessible name shared by every thumb. |
aria-labelledby | string | — | ID reference for an external accessible name. |
aria-describedby | string | — | ID reference for supporting text announced with each thumb. |
aria-invalid | boolean | "grammar" | "spelling" | "true" | "false" | — | Marks the underlying range input as invalid. |
aria-errormessage | string | — | ID of the error message associated with the underlying range input. |
disabled | boolean | false | Disables the slider. |
thumbAlignment | "center" | "edge" | "edge-client-only" | "center" | How thumbs align with the control edges. |
thumbCollisionBehavior | "push" | "swap" | "none" | "push" | How range thumbs behave when they collide. |
render | ReactElement | ((props, state) => ReactElement) | — | Replaces the root element. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the root element. |
className | string | — | Tailwind classes merged into the outermost root. |
style | CSSProperties | — | Inline styles merged into the same element as className. |
ui | { root?: ClassValue; control?: ClassValue; track?: ClassValue; indicator?: ClassValue; thumb?: ClassValue } | — | Tailwind classes for internal slots, keyed by data-slot. |
| Attribute | Description |
|---|---|
data-dragging | Present while a thumb is being dragged. |
data-orientation | Indicates the orientation (horizontal or vertical). |
data-disabled | Present when the slider is disabled. |
data-index | Indicates the thumb index on range sliders. |
data-valid | Present when the slider is valid and wrapped in Field. |
data-invalid | Present when the slider is invalid and wrapped in Field. |
data-touched | Present after the slider is touched while wrapped in Field. |
data-dirty | Present after the slider value changes while wrapped in Field. |
data-slot | Marks internal parts (root, control, track, indicator, thumb) for styling. |
data-focused | Present when the slider is focused while wrapped in Field. |
The component uses the shared glass material. Tune shared --ui-glass-* tokens on a parent, use className for layout, and use ui for internal slots keyed by data-slot. Component-specific values live in src/theme/slider.ts. See the theming guide for token layers and presets.