Slider
Picks a value or a range of values by dragging a thumb along a track.
<div className="grid w-full max-w-xs gap-3">
<Label id="risk-threshold-label">Risk score threshold</Label>
<Slider defaultValue={[70]} aria-labelledby="risk-threshold-label" />
</div>Usage
import { Label } from "@zenoxai/ui/components/label"
import { Slider } from "@zenoxai/ui/components/slider"
<Label id="risk-threshold-label">Risk score threshold</Label>
<Slider defaultValue={[70]} aria-labelledby="risk-threshold-label" />
Use a slider when an approximate value is good enough and seeing it relative to the range helps: thresholds, sampling rates, score ranges. When the user needs an exact value, use a Number Input, or pair the slider with one.
Pass a number for one thumb (defaultValue={70}) or an array with one entry per thumb
([4, 8.9] for a range). Without a value the slider has one thumb.
min and max default to 0 and 100; step defaults to 1. The slider fills the width of
its container.
Examples
With the value
The slider does not print its value. Keep it in state with value and onValueChange and
show it next to the label. onValueChange is typed number | number[]; with an array value
it always receives an array.
function SliderWithValue() {
const [sampling, setSampling] = React.useState([25])
return (
<div className="grid w-full max-w-xs gap-3">
<div className="flex items-center justify-between">
<Label id="sampling-label">Log sampling rate</Label>
<span className="text-sm text-text-secondary tabular-nums">
{sampling[0]}%
</span>
</div>
<Slider
value={sampling}
onValueChange={(value) => setSampling(value as number[])}
step={5}
aria-labelledby="sampling-label"
/>
</div>
)
}Range
Two entries render two thumbs. minStepsBetweenValues keeps them a number of steps apart.
function SliderRange() {
const [range, setRange] = React.useState([4, 8.9])
return (
<div className="grid w-full max-w-xs gap-3">
<div className="flex items-center justify-between">
<Label id="cvss-label">CVSS score</Label>
<span className="text-sm text-text-secondary tabular-nums">
{range[0]?.toFixed(1)} to {range[1]?.toFixed(1)}
</span>
</div>
<Slider
value={range}
onValueChange={(value) => setRange(value as number[])}
min={0}
max={10}
step={0.1}
minStepsBetweenValues={5}
aria-labelledby="cvss-label"
/>
</div>
)
}Disabled
<div className="grid w-full max-w-xs gap-3">
<Label id="retention-label">Retention (set by your plan)</Label>
<Slider
defaultValue={[30]}
max={90}
disabled
aria-labelledby="retention-label"
/>
</div>Accessibility
- Each thumb is a native
<input type="range">. Name the slider witharia-labelledbypointing at a visible label’sid; the slider passes it to every thumb. To name thumbs individually (“Minimum”, “Maximum”), passthumbLabels.aria-labelonSliderandhtmlForon a label do not reach the thumbs. - A thumb shows the focus ring when its input has keyboard focus, the same 3px ring as the other form controls.
- Arrow keys move a thumb by
step; Shift plus an arrow, Page Up and Page Down bylargeStep(10 by default); Home and End tominandmax. - In a range, screen readers announce the thumbs as “start range” and “end range”.
- Use
onValueCommittedinstead ofonValueChangefor expensive work, such as a request: it fires once when the user releases the thumb.
API reference
Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.
Slider
Slider picks a number, or a range with two thumbs, by dragging along a track: a threshold, a volume, a price range. When the exact figure matters, use NumberInput, alone or next to it.
| Prop | Type | Default |
|---|---|---|
defaultValue | number | readonly number[]The uncontrolled value of the slider when it's initially rendered. | - |
disabled | booleanWhether the slider should ignore user interaction. | false |
form | stringIdentifies the form that owns the slider inputs. Useful when the slider is rendered outside the form. | - |
format | NumberFormatOptionsOptions to format the value. | - |
largeStep | numberThe granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down. | 10 |
locale | LocalesArgumentThe locale used by `Intl.NumberFormat` when formatting the value. Defaults to the user's runtime locale. | - |
max | numberThe maximum allowed value of the slider. Should not be equal to min. | 100 |
min | numberThe minimum allowed value of the slider. Should not be equal to max. | 0 |
minStepsBetweenValues | numberThe minimum steps between values in a range slider. | 0 |
name | stringIdentifies the field when a form is submitted. | - |
onValueChange | ((value: number | readonly number[], eventDetails: SliderRootChangeEventDetails) => void)Callback function that is fired when the slider's value changed. Receives the new value as the first argument; the originating event is available as `eventDetails.event`. The value is also reflected on `eventDetails.event.target.value` for form integration. | - |
onValueCommitted | ((value: number | readonly number[], eventDetails: SliderRootCommitEventDetails) => void)Callback 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. | - |
orientation | "horizontal" | "vertical"The component orientation. | 'horizontal' |
render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderRootState>Allows you to replace the component's HTML element with a different tag, or compose it with another component. | - |
step | numberThe granularity with which the slider can step through values. (A "discrete" slider.) The `min` prop serves as the origin for the valid values. We recommend (max - min) to be evenly divisible by the step. | 1 |
thumbAlignment | "center" | "edge" | "edge-client-only"How the thumb(s) are aligned relative to `Slider.Control` when the value is at `min` or `max`: - `center`: The center of the thumb is aligned with the control edge - `edge`: The thumb is inset within the control such that its edge is aligned with the control edge - `edge-client-only`: Same as `edge` but renders after React hydration on the client, reducing bundle size in return | 'center' |
thumbCollisionBehavior | "none" | "push" | "swap"Controls how thumbs behave when they collide during pointer interactions. | 'push' |
thumbLabels | string[]Already-translated accessible name of each thumb, in order. | - |
value | number | readonly number[]The value of the slider. For range sliders, provide an array with one value per thumb. | - |