import * as React from "react";
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function SliderBasic() {
const [volume, setVolume] = React.useState(60);
return (
<Field className="max-w-sm">
<div className="flex items-center justify-between">
<FieldLabel>Volume</FieldLabel>
<span className="text-sm text-muted-foreground tabular-nums">{volume}%</span>
</div>
<Slider value={volume} onValueChange={setVolume} />
</Field>
);
}- Add the registryOnce per project
pnpm dlx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json - Add slider
pnpm dlx shadcn@latest add @jarvis/slider
Usage
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export function ZoomSlider() {
return (
<Field>
<FieldLabel>Zoom</FieldLabel>
<Slider defaultValue={100} min={25} max={400} />
</Field>
);
}The range is 0 to 100 unless you set min and max. Name the slider with a FieldLabel in the
same Field, or an aria-label.
Examples
Range
Pass an array of two values for two thumbs. Name each one with getAriaLabel.
import * as React from "react";
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function SliderRange() {
const [range, setRange] = React.useState([20, 75]);
return (
<Field className="max-w-sm">
<div className="flex items-center justify-between">
<FieldLabel>Budget</FieldLabel>
<span className="text-sm text-muted-foreground tabular-nums">
${range[0]}k – ${range[1]}k
</span>
</div>
<Slider
value={range}
onValueChange={setRange}
getAriaLabel={(index) => (index === 0 ? "Minimum budget" : "Maximum budget")}
/>
</Field>
);
}Steps
step sets the increment.
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function SliderStep() {
return (
<Field className="max-w-sm">
<FieldLabel>Quality</FieldLabel>
<Slider defaultValue={50} step={25} />
</Field>
);
}Vertical
Set orientation="vertical" and give the parent a height.
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function SliderVertical() {
return (
<div className="flex gap-8">
<Field className="h-44 w-fit items-center gap-3">
<Slider orientation="vertical" defaultValue={40} />
<FieldLabel>Bass</FieldLabel>
</Field>
<Field className="h-44 w-fit items-center gap-3">
<Slider orientation="vertical" defaultValue={[25, 70]} />
<FieldLabel>Band</FieldLabel>
</Field>
</div>
);
}Disabled
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function SliderDisabled() {
return (
<Field className="max-w-sm">
<FieldLabel>Brightness</FieldLabel>
<Slider defaultValue={30} disabled />
</Field>
);
}Props
onValueChange receives the same shape as value: a number, or an array of numbers.
| Part | Extends |
|---|---|
| Slider | Base UI's Slider.Root |
The tables leave out className, style and render. Parts built on Base UI take them as its styling and composition guides describe.
Slider
| Prop | Type | Default |
|---|---|---|
defaultValueThe uncontrolled value of the slider when it's initially rendered. To render a controlled slider, use the | number | readonly number[] | — |
disabledWhether the slider should ignore user interaction. | boolean | false |
formatOptions to format the value. | Intl.NumberFormatOptions | — |
localeThe locale used by | Intl.LocalesArgument | — |
maxThe maximum allowed value of the slider. Should not be equal to min. | number | 100 |
minThe minimum allowed value of the slider. Should not be equal to max. | number | 0 |
minStepsBetweenValuesThe minimum steps between values in a range slider. | number | 0 |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the slider inputs. Useful when the slider is rendered outside the form. | string | — |
orientationThe component orientation. | "horizontal" | "vertical" | 'horizontal' |
stepThe granularity with which the slider can step through values. (A "discrete" slider.)
The | number | 1 |
largeStepThe granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down. | number | 10 |
thumbAlignmentHow the thumb(s) are aligned relative to
| "center" | "edge" | "edge-client-only" | "edge" |
thumbCollisionBehaviorControls how thumbs behave when they collide during pointer interactions.
| "none" | "push" | "swap" | 'push' |
valueThe value of the slider. For range sliders, provide an array with one value per thumb. | number | readonly number[] | — |
onValueChangeCallback function that is fired when the slider's value changed.
Receives the new value as the first argument; the originating event is
available as The
| ((value: number | readonly number[], eventDetails: Slider.Root.ChangeEventDetails) => void) | — |
onValueCommittedCallback function that is fired when a value change is committed. Does not fire if the value did not change, or if the change was canceled. Warning: This is a generic event, not a change event. The
| ((value: number | readonly number[], eventDetails: Slider.Root.CommitEventDetails) => void) | — |
getAriaLabelNames each thumb by its index, such as "Minimum" and "Maximum" on a range. Without it, | ((index: number) => string) | null | — |
getAriaValueTextDescribes each thumb's value to screen readers, such as "50%" as "Half volume". | ((formattedValue: string, value: number, index: number) => string) | null | — |