Slider
Picks a number or a range by dragging a thumb along a track.
Installation
The CLI installs the Radix or Base UI file to match your project.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- To pick a number from a range where the feel matters more than the exact value, like a discount, a volume or a probability.
- To pick a range with two thumbs, like a price filter, as the Range example shows.
- When the range is small enough to move through with the arrow keys.
Don't use it
- When people need an exact number, or the range is very large. Use Input with
type="number", or put one next to the slider. - When the choice is one of a few named options. Use Radio Group or Toggle Group.
- To show progress, not to choose. Use Progress.
Usage
Pass the value as an array, one number per thumb, and name the slider with aria-labelledby pointing at a visible label.
import { useId } from "react"
import { Label } from "@/components/ui/label"
import { Slider } from "@/components/ui/slider"
export function Probability() {
const id = useId()
return (
<div className="grid gap-1">
<Label id={`${id}-label`}>Probability</Label>
<Slider aria-labelledby={`${id}-label`} defaultValue={[60]} />
</div>
)
}When you control it, let onValueChange take a number as well as an array: setValue(Array.isArray(next) ? next : [next]). In Base UI projects, moving a single thumb by pointer passes a bare number, though the types say array, and kept as a number the slider draws a second thumb. For expensive work, act when the drag ends instead: onValueCommit in Radix projects, onValueCommitted in Base UI projects.
Examples
Range
Two thumbs pick a range, one for each number in `defaultValue`.
Disabled
A slider set with `disabled`: it can't take focus or move.
Vertical
A slider that runs bottom to top, set with `orientation="vertical"`.
API reference
Slider
| Prop | Type | Default |
|---|---|---|
min | number | 0 |
max | number | 100 |
Also takes every Radix Slider.Root (opens in a new tab) prop.
SLDS mapping
SLDS styles a native range input, slds-slider__range in slds-slider. The track, the fill and each thumb match that input's track and thumb, and orientation="vertical" is slds-slider_vertical. The value text after the slider is slds-slider__value, which the slider doesn't render; add it yourself, as the Discount example does.
Known gaps:
- SLDS's track has no fill. Here the range fills in the thumb's color.
- SLDS's slider is one native input, so it has no range slider.
- SLDS's range text in the label ("0 - 100",
slds-slider-label__range) isn't part of Slider. Add it to the label if you want it.
Keyboard interactions
| Keys | Action |
|---|---|
| Right or Up arrow | Increases the value by one step. |
| Left or Down arrow | Decreases the value by one step. |
| Shift + arrow, Page Up or Page Down | Changes the value by ten steps. |
| Home, End | Moves to the minimum or the maximum. |
Accessibility
- Each thumb takes its name from the root's
aria-labelledby. Anaria-labelon the root reaches no thumb, so use a visible label. - Each thumb announces its value, so make the value text next to the slider
aria-hidden. - A disabled slider can't take focus. Say why in nearby text if it matters.
Responsive behavior
- A horizontal slider fills its container's width. A vertical one fills its container's height, so give that container a height, as the Vertical example does.
Rules
- Don't restyle the track, thumb or fill colors. They come from the theme.