Shadcn Slider
Free shadcn/ui slider component for React — built on Radix. A draggable range input: a single thumb, a two-thumb range, a value label, stepped ticks, and a volume control.
Installation
{
"registries": {
"@designrevision": "https://registry.designrevision.com/r/{name}.json"
}
}
Add to your existing components.json. Requires shadcn/ui v2.3+.
Packages
Props
defaultValue / value
= [min, max]
number[]
Thumb positions. One number = one thumb; two = a range slider.
min / max / step
= 0 / 100 / 1
number
Range bounds and increment.
orientation
= "horizontal"
"horizontal" | "vertical"
Slider direction.
A Radix slider. Pass an array to value / defaultValue — one number renders a single thumb, two render a range slider. Set min, max, step for the scale and onValueChange to read it. Works horizontally or vertically (orientation="vertical" needs a height).
"use client"
import * as React from "react"
import * as SliderPrimitive from "@radix-ui/react-slider"
import { cn } from "@/lib/utils"
function Slider({
className,
defaultValue,
value,
min = 0,
max = 100,
...props
}: React.ComponentProps<typeof SliderPrimitive.Root>) {
const _values = React.useMemo(
() =>
Array.isArray(value)
? value
: Array.isArray(defaultValue)
? defaultValue
: [min, max],
[value, defaultValue, min, max]
)
return (
<SliderPrimitive.Root
data-slot="slider"
defaultValue={defaultValue}
value={value}
min={min}
max={max}
className={cn(
"relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
className
)}
{...props}
>
<SliderPrimitive.Track
data-slot="slider-track"
className={cn(
"bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
)}
>
<SliderPrimitive.Range
data-slot="slider-range"
className={cn(
"bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
)}
/>
</SliderPrimitive.Track>
{Array.from({ length: _values.length }, (_, index) => (
<SliderPrimitive.Thumb
data-slot="slider-thumb"
key={index}
className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
/>
))}
</SliderPrimitive.Root>
)
}
export { Slider }
Examples
Basic
The canonical single-thumb slider — drag to pick one value.
Range
Two thumbs select a min and max, with a live price readout.
Packages
Props
No props documented yet.
"use client"
import * as React from "react"
import { Slider } from "@/components/ui/slider"
export default function SliderRange01() {
const [value, setValue] = React.useState([200, 800])
return (
<div className="w-full max-w-sm space-y-3">
<div className="flex items-center justify-between text-sm">
<span className="text-muted-foreground">Price range</span>
<span className="font-medium tabular-nums">
${value[0]} – ${value[1]}
</span>
</div>
<Slider
value={value}
onValueChange={setValue}
min={0}
max={1000}
step={10}
/>
</div>
)
}
With value label
A controlled slider that shows its current value beside a label.
Packages
Props
No props documented yet.
"use client"
import * as React from "react"
import { Label } from "@/components/ui/label"
import { Slider } from "@/components/ui/slider"
export default function SliderValue01() {
const [value, setValue] = React.useState([33])
return (
<div className="w-full max-w-sm space-y-3">
<div className="flex items-center justify-between">
<Label>Brightness</Label>
<span className="text-sm font-medium tabular-nums">{value[0]}%</span>
</div>
<Slider value={value} onValueChange={setValue} max={100} step={1} />
</div>
)
}
Stepped with ticks
Snaps to fixed steps, with tick labels marked below the track.
Packages
Props
No props documented yet.
import { Slider } from "@/components/ui/slider"
const ticks = [0, 20, 40, 60, 80, 100]
export default function SliderSteps01() {
return (
<div className="w-full max-w-sm space-y-3">
<Slider defaultValue={[40]} max={100} step={20} />
<div className="text-muted-foreground flex justify-between text-xs tabular-nums">
{ticks.map((tick) => (
<span key={tick}>{tick}</span>
))}
</div>
</div>
)
}
Volume control
A slider flanked by mute and volume icons — the media-control pattern.
Packages
Props
No props documented yet.
"use client"
import * as React from "react"
import { Volume2, VolumeX } from "lucide-react"
import { Slider } from "@/components/ui/slider"
export default function SliderVolume01() {
const [volume, setVolume] = React.useState([60])
return (
<div className="flex w-full max-w-sm items-center gap-3">
<VolumeX className="text-muted-foreground size-4 shrink-0" />
<Slider
value={volume}
onValueChange={setVolume}
max={100}
step={1}
aria-label="Volume"
/>
<Volume2 className="text-muted-foreground size-4 shrink-0" />
</div>
)
}
The Shadcn Slider is a draggable range input for React, built on Radix. Drag a thumb along the track to pick a value — or add a second thumb for a min/max range. Radix handles the dragging, keyboard, and ARIA; the shadcn styling gives you the track, range, and thumb. The examples below cover a basic slider, a price range, a value label, a stepped scale, and a volume control.
The shape
<Slider defaultValue={[50]} min={0} max={100} step={1} />
The value is always an array — one entry per thumb. A single-element array is a normal slider; a two-element array is a range.
Range slider
Pass two values and Radix renders two thumbs:
<Slider defaultValue={[200, 800]} min={0} max={1000} step={10} />
Read both ends back from onValueChange, which fires with the full array on every drag.
Reading the value
Control it to show or sync the value:
const [value, setValue] = React.useState([50])
<Slider value={value} onValueChange={setValue} />
<span>{value[0]}</span>
For a form that only needs the value on submit, use defaultValue and read it from the field instead.
Steps and scale
step snaps the thumb; min and max bound it:
<Slider min={0} max={100} step={20} />
For a labelled scale, render your own tick marks below the track and space them to line up with the steps — the Stepped with ticks example shows the pattern.
Common patterns
- Price range — a two-thumb range with a
$min – $maxreadout (the Range example). - Brightness / opacity — a single value with a live percentage (the Value label example).
- Volume — a slider between mute and volume icons (the Volume control example).
Accessibility
Each thumb is focusable and driven by the keyboard: Arrow keys step, Page Up / Page Down jump, and Home / End snap to min / max. Radix sets role="slider" with aria-valuemin, aria-valuemax, and aria-valuenow, so the value is announced. Add an aria-label (or a visible <Label>) so the control's purpose is clear.