---
import { Slider } from "@/components/ui/slider"
---
<Slider defaultValue={75} max={100} step={1} class="mx-auto w-full max-w-xs" />Installation
npx shadcn@latest add @fulldev/slider
Usage
import { Slider } from "@/components/ui/slider"
<Slider defaultValue={33} max={100} step={1} />
A single number renders one thumb, a pair renders a range. Thumbs use
thumbAlignment="edge" by default, so they stay within the track at the
minimum and maximum. Use thumbAlignment="center" to center them over the
track endpoints.
Range
Use an array with two values for a range slider.
---
import { Slider } from "@/components/ui/slider"
---
<Slider
defaultValue={[25, 50]}
max={100}
step={5}
class="mx-auto w-full max-w-xs"
/>Multiple Thumbs
The official example has three thumbs. The Astro slider supports at most two, so this example is in the React Slider docs only.
Vertical
Use orientation="vertical" for a vertical slider.
---
import { Slider } from "@/components/ui/slider"
---
<div class="mx-auto flex w-full max-w-xs items-center justify-center gap-6">
<Slider
defaultValue={50}
max={100}
step={1}
orientation="vertical"
class="h-40"
/>
<Slider
defaultValue={25}
max={100}
step={1}
orientation="vertical"
class="h-40"
/>
</div>Controlled
Listen to the slider:change event on the root to read the value. Dispatch
slider:set with { value } to set it.
---
import { Label } from "@/components/ui/label"
import { Slider } from "@/components/ui/slider"
const value = [0.3, 0.7]
---
<div class="mx-auto grid w-full max-w-xs gap-3" data-slider-controlled>
<div class="flex items-center justify-between gap-2">
<Label data-slider-label>Temperature</Label>
<span class="text-sm text-muted-foreground" data-slider-value>
{value.join(", ")}
</span>
</div>
<Slider defaultValue={[value[0], value[1]]} min={0} max={1} step={0.1} />
</div>
<script>
const initialize = () => {
for (const root of document.querySelectorAll("[data-slider-controlled]")) {
if (root.hasAttribute("data-bound")) continue
root.setAttribute("data-bound", "")
// Name each thumb after the visible label: the thumbs are the
// focusable sliders, not the root.
const name = root
.querySelector("[data-slider-label]")
?.textContent?.trim()
const thumbs = root.querySelectorAll('[data-slot="slider-thumb"]')
thumbs.forEach((thumb, index) =>
thumb.setAttribute(
"aria-label",
thumbs.length > 1
? `${name} ${index === 0 ? "minimum" : "maximum"}`
: `${name}`
)
)
const output = root.querySelector("[data-slider-value]")
root
.querySelector('[data-slot="slider"]')
?.addEventListener("slider:change", (event) => {
const { value } = (event as CustomEvent<{ value: number | number[] }>)
.detail
if (output) output.textContent = [value].flat().join(", ")
})
}
}
initialize()
document.addEventListener("astro:page-load", initialize)
</script>Disabled
Use the disabled prop to disable the slider.
---
import { Slider } from "@/components/ui/slider"
---
<Slider
defaultValue={50}
max={100}
step={1}
disabled
class="mx-auto w-full max-w-xs"
/>RTL
Set dir="rtl" on the slider or a parent element.
---
import { Slider } from "@/components/ui/slider"
const translations = {
en: {
dir: "ltr",
values: {},
},
ar: {
dir: "rtl",
values: {},
},
he: {
dir: "rtl",
values: {},
},
} as const
const { dir } = translations.ar
---
<Slider
defaultValue={75}
max={100}
step={1}
class="mx-auto w-full max-w-xs"
dir={dir}
/>API Reference
Source: src/components/ui/slider
| Prop | Type | Default |
|---|---|---|
defaultValue | number | [number, number] | min |
min | number | 0 |
max | number | 100 |
step | number | 1 |
largeStep | number | step * 10 |
orientation | "horizontal" | "vertical" | "horizontal" |
thumbAlignment | "center" | "edge" | "edge-client-only" | "edge" |
disabled | boolean | false |
See the data-slot docs for events and keyboard behavior.