<Stack
width="320px"
maxWidth="100%"
>
<Slider.Root>
<Slider.Label>Volume</Slider.Label>
<Slider.Control name="playground-volume" defaultValue={40} />
<Slider.HelperText>Drag to adjust the volume.</Slider.HelperText>
<Slider.ErrorMessage>Volume is too high.</Slider.ErrorMessage>
</Slider.Root>
</Stack>Features
- Single values or ranges.
- Custom bounds and steps.
- Custom tooltip formatting.
- Live and final value updates.
- Horizontal or vertical layout.
- Helper text, errors, and disabled states.
Anatomy
Root groups the field, Label names it, and Control is the slider and requires name. HelperText is optional.
<Slider.Root>
<Slider.Label>Volume</Slider.Label>
<Slider.Control name="volume" />
<Slider.HelperText>Adjust the playback volume.</Slider.HelperText>
</Slider.Root>Bounds and Steps
Set min, max, and step to define the available values, and defaultValue to choose the starting point.
import { Slider } from "@vortexlabs/vortex";
<Slider.Root>
<Slider.Label>Volume</Slider.Label>
<Slider.Control name="volume" min={0} max={100} step={5} defaultValue={40} />
<Slider.HelperText>Adjust in steps of five.</Slider.HelperText>
</Slider.Root>Range Selection
Set range and give each handle a minLabel and maxLabel. Use minName and maxName to submit separate form values, or one shared name.
<Slider.Root>
<Slider.Label>Price range</Slider.Label>
<Slider.Control
range
minName="min-price"
maxName="max-price"
minLabel="Minimum price"
maxLabel="Maximum price"
min={0}
max={500}
step={25}
defaultMinValue={100}
defaultMaxValue={350}
/>
<Slider.HelperText>Choose a minimum and maximum price.</Slider.HelperText>
</Slider.Root>Controlled Values and Commit Events
Use value with onChange to track the value as it changes. onChangeCommit fires once the interaction ends, which suits expensive work like applying a filter.
"use client";
import { Slider } from "@vortexlabs/vortex";
import { useState } from "react";
export const SliderControlledExample = () => {
const [value, setValue] = useState(40);
const [committed, setCommitted] = useState(40);
return (
<Slider.Root>
<Slider.Label>Search radius</Slider.Label>
<Slider.Control
name="radius"
min={5}
max={100}
step={5}
value={value}
onChange={({ value }) => setValue(value)}
onChangeCommit={({ value }) => setCommitted(value)}
/>
<Slider.HelperText>
Current: {value} km. Applied: {committed} km.
</Slider.HelperText>
</Slider.Root>
);
};Controlled Range
A controlled range takes minValue and maxValue. onChange reports both, so update them together.
"use client";
import { Slider } from "@vortexlabs/vortex";
import { useState } from "react";
export const SliderRangeExample = () => {
const [range, setRange] = useState({ minValue: 20, maxValue: 70 });
return (
<Slider.Root>
<Slider.Label>Temperature range</Slider.Label>
<Slider.Control
range
name="temperature"
minLabel="Minimum temperature"
maxLabel="Maximum temperature"
min={0}
max={100}
minValue={range.minValue}
maxValue={range.maxValue}
onChange={({ minValue, maxValue }) => setRange({ minValue, maxValue })}
/>
<Slider.HelperText>
{range.minValue}–{range.maxValue} degrees
</Slider.HelperText>
</Slider.Root>
);
};Value Formatting
Use renderValue to format the tooltip and the value screen readers announce. Pass false to hide the tooltip.
"use client";
import { Slider, Stack } from "@vortexlabs/vortex";
export const SliderFormatExample = () => {
return (
<Stack gap={6} width="100%">
<Slider.Root>
<Slider.Label>Playback speed</Slider.Label>
<Slider.Control
name="playback-speed"
min={0.5}
max={2}
step={0.25}
defaultValue={1}
renderValue={({ value }) => value + "× speed"}
/>
</Slider.Root>
<Slider.Root>
<Slider.Label>Background intensity</Slider.Label>
<Slider.Control name="intensity" defaultValue={30} renderValue={false} />
</Slider.Root>
</Stack>
);
};Vertical
Set orientation="vertical" and place the slider in a container with a set height.
<Stack height="16rem">
<Slider.Root>
<Slider.Label>Volume</Slider.Label>
<Slider.Control name="vertical-volume" orientation="vertical" defaultValue={60} />
</Slider.Root>
</Stack>Disabled and Error States
Set disabled or error on Slider.Root. Slider.ErrorMessage shows only when error is set.
<Stack gap={6} width="100%">
<Slider.Root disabled>
<Slider.Label>Managed volume</Slider.Label>
<Slider.Control name="managed-volume" defaultValue={50} />
</Slider.Root>
<Slider.Root error>
<Slider.Label>Storage allocation</Slider.Label>
<Slider.Control name="storage-allocation" defaultValue={90} />
<Slider.ErrorMessage>This allocation exceeds your remaining storage.</Slider.ErrorMessage>
</Slider.Root>
</Stack>Accessibility
step.Slider.Label, or an aria-label through inputAttributes, to name the slider.minLabel and maxLabel when range is set.renderValue when the raw number needs units to make sense.