Slider
Range slider input primitive supporting standard track/thumb and tactile capsule pill variants, single or dual thumb values, auto/custom track marks, and radius customization.
// Radix — @radix-ui/react-slider
import { CapsuleSlider, Slider } from "@shavin/ui";Capsule variant — plain continuous bar vs discrete stops
Plain smooth bar (no ticks)
Brightness50%
Brightness50%
Theme Accent with auto stops (step=5)
Volume65%
Volume65%
Monochrome inverting (color="mono")
Speed Factor1.5x
Speed Factor1.5x
Component Source
const [brightness, setBrightness] = useState(50);
const [volume, setVolume] = useState(65);
const [speed, setSpeed] = useState(30);
{/* 1. Plain smooth slider bar (continuous / no stop ticks) */}
<Slider
variant="capsule"
label="Brightness"
value={brightness}
onValueChange={setBrightness}
min={0}
max={100}
step={1}
showStops={false}
formatValue={(v) => `${v}%`}
/>
{/* 2. Theme Accent color with discrete stop marks */}
<Slider
variant="capsule"
color="accent"
label="Volume"
value={volume}
onValueChange={setVolume}
min={0}
max={100}
step={5}
marks="auto"
formatValue={(v) => `${v}%`}
/>
{/* 3. Monochrome inverting color (bg-fg / text-canvas) */}
<Slider
variant="capsule"
color="mono"
label="Speed Factor"
value={speed}
onValueChange={setSpeed}
min={0}
max={100}
step={10}
marks="auto"
formatValue={(v) => `${(v / 20).toFixed(1)}x`}
/>Single value (standard track)
40
Component Source
const [value, setValue] = useState(40);
<Slider value={value} onValueChange={setValue} min={0} max={100} step={1} />Range (two thumbs)
20 – 70
Component Source
const [range, setRange] = useState([20, 70]);
<Slider value={range} onValueChange={setRange} min={0} max={100} step={1} />Stops (marks="auto" auto-calculated from step)
Auto-calculated ticks (step=20, marks="auto")
40
Milestone marks (step=5, marks=[0, 25, 50, 75, 100])
50
Component Source
const [value, setValue] = useState(40);
{/* marks="auto" automatically renders ticks at each step quantum */}
<Slider
value={value}
onValueChange={setValue}
min={0}
max={100}
step={20}
marks="auto"
/>
{/* Custom milestone marks array: marks={[0, 25, 50, 75, 100]} */}
<Slider
value={value}
onValueChange={setValue}
min={0}
max={100}
step={5}
marks={[0, 25, 50, 75, 100]}
/>Radius — explicit overrides vs theme
rounded (radius="full", fixed)
square (radius="none", fixed)
inherit (tracks the Radius Configurator)
Component Source
{/* Explicit — fixed regardless of the Configurator */}
<Slider defaultValue={50} radius="full" /> {/* rounded */}
<Slider defaultValue={50} radius="none" /> {/* square */}
{/* Inherit — tracks the global Radius Configurator */}
<Slider defaultValue={50} radius="inherit" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "capsule" | — | Visual variant: "default" (standard track & thumb) or "capsule" (sleek compact pill with embedded label and live fill value). |
| value | number[] | number | — | Current value: number[] (e.g. [40]) or single number (e.g. 40). |
| defaultValue | number[] | number | value | Default value when uncontrolled. |
| onValueChange | (val: any) => void | — | Value change callback. |
| marks | number[] | "auto" | — | Optional array of numeric tick mark values drawn on the track (e.g. [0, 50, 100]) or "auto" for auto-calculated stops based on step. |
| label | ReactNode | — | Label text or ReactNode displayed inside capsule slider track (when variant="capsule"). |
| formatValue | (val: number) => string | — | Formatter function for displaying formatted value string in capsule mode (e.g. (v) => `${v}px`). |
| color | "accent" | "mono" | accent | Fill color style in capsule mode: "accent" (active theme accent) or "mono" (monochrome inverting). Default "accent". |
| showStops | boolean | true | Whether to show subtle stop ticks on hover in capsule mode. Default true for discrete steps (3–30). |
| radius | "none" | "small" | "medium" | "large" | "full" | "inherit" | "concentric" | "inherit" | — |