Slider provides a drag-based numeric input for continuous or stepped values,
built on Radix Slider primitives.
When to use
- Let users adjust numeric settings with immediate visual feedback.
- Select a bounded range (for example, minimum and maximum thresholds).
- Replace text/number inputs when precision beyond the chosen
stepis not required.
Behavior notes
- Pass one value (
[n]) for a single-thumb slider, two values ([min, max]) for range selection. - Use
valueandonValueChangefor controlled usage. - Configure bounds with
min,max, and increments withstep.
Example
const [value, setValue] = useState([35]);
<Slider
value={value}
onValueChange={setValue}
min={0}
max={100}
step={1}
aria-label='Volume'
/>;
Preview
Threshold
40%
Range
20 - 80
Usage
import React from 'react';
import { Text, Slider } from '@branditdev/ui';
export function SliderDemo() {
const [singleValue, setSingleValue] = React.useState([40]);
const [rangeValue, setRangeValue] = React.useState([20, 80]);
return (
<div className='w-full max-w-md space-y-5'>
<div className='space-y-2'>
<div className='flex items-center justify-between'>
<Text variant='body-sm'>Threshold</Text>
<Text variant='body-sm'>{singleValue[0]}%</Text>
</div>
<Slider
value={singleValue}
onValueChange={setSingleValue}
min={0}
max={100}
step={1}
aria-label='Threshold slider'
/>
</div>
<div className='space-y-2'>
<div className='flex items-center justify-between'>
<Text variant='body-sm'>Range</Text>
<Text variant='body-sm'>
{rangeValue[0]} - {rangeValue[1]}
</Text>
</div>
<Slider
value={rangeValue}
onValueChange={setRangeValue}
min={0}
max={100}
step={1}
aria-label='Range slider'
/>
</div>
</div>
);
}
API
Slider(
props):Element
Defined in: components/slider/slider.tsx:13
Slider UI component.
Parameters
| Name | Type | Optional | Default | Description |
|---|---|---|---|---|
| props | SliderProps & RefAttributes<HTMLSpanElement> | no | - | Component properties. |
Returns
Element
Rendered component.
Source
import { Slider as SliderPrimitive } from 'radix-ui';
import React from 'react';
import { cn } from '@branditdev/ui';
export 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(
'relative grow overflow-hidden rounded-full bg-muted 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(
'absolute bg-primary 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='block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50'
/>
))}
</SliderPrimitive.Root>
);
}