Slider
Pick a number, or a range, by dragging along a track. Tint track, ink range, an ink thumb on a hairline that presses under motion-safe. Source: src/components/ui/slider.tsx.
Default
Show the value next to the label so the person never has to guess. Drag, click the track, or focus the thumb and use the arrow keys.
Range
Pass two values for a min and max. The thumbs can't cross.
With icons
End icons say what low and high mean when the value has no unit. Keep them aria-hidden; the slider's label carries the meaning.
Change and commit
Update the readout on change; write to the server on commit. Drag and watch the two numbers.
- onValueChange
- 50
- onValueCommit
- 50
States and orientation
Disabled fades the whole control. Vertical needs a parent with a height.
Known gaps: no invalid style, no tick marks or value tooltip, and the wrapper gives no way to pass an accessible name to each thumb (the role="slider" element). aria-label or aria-labelledby land on the root. Until the wrapper forwards a thumb label, keep a visible label and readout beside every slider.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue | number[] | [min, max] | Always an array. One entry is one thumb, two make a range. With neither set, the wrapper renders two thumbs at min and max. |
| onValueChange | (value: number[]) => void | — | Every step while dragging or on arrow keys. |
| onValueCommit | (value: number[]) => void | — | Once, on pointer up or key up. Save here. |
| min / max | number | 0 / 100 | The range. |
| step | number | 1 | Increment. Shift+Arrow and Page Up/Down jump by 10 steps. |
| minStepsBetweenThumbs | number | 0 | Keeps range thumbs apart. |
| orientation | "horizontal" | "vertical" | "horizontal" | Vertical fills its parent's height. |
| disabled | boolean | false | 50% opacity, no interaction. |
| ...props | ComponentProps<typeof SliderPrimitive.Root> | — | inverted, name, dir pass to Radix. className merges onto the root. No size or variant props: a 6px track and a 16px thumb. |
Best practices
When to use
- A value where the rough position matters more than the exact number: temperature, volume, a weight filter, a scrub.
- An exact number (a budget, a count) is an Input with type="number", or both side by side.
Behavior
- Always show the current value, in tabular-nums so it doesn't jitter while dragging.
- Save on onValueCommit, not on every onValueChange.
- Pick a step that matches the precision people need; 0.1 on a 0–2 scale, 5 on a 0–100 filter.
Accessibility
- Arrow keys step, Shift+Arrow and Page Up/Down jump, Home/End go to the ends.
- The thumb is 16px; on touch, give the slider its full row width and enough vertical room around it.
- See the thumb-label gap above: keep a visible label next to the control.
Content
- Label the ends when the scale isn't obvious: Precise to Creative, not 0 to 2.