import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
<Slider defaultValue={40} style={{ width: '100%' }}>
<SliderTrack>
<SliderRange />- Browser support
- Widely available
- Chrome 111
- Edge 111
- Firefox 121
- Safari 15.4
- Safari on iOS 15.4
- Bundle size
- :has()
- Oklab and OkLCh — comes from the design tokens
- clip-path
- Logical properties
- :dir() — only right-to-left layouts depend on it
- Vertical form controls — only the vertical orientation depends on it
- :focus-visible
- :where()
Summary
Slider is a compound component for selecting one or several numbers from a bounded range. Every SliderThumbInput is a native <input type="range"> laid over one SliderTrack, so keyboard, focus, form submission and reset, and assistive technologies behave like the native element. Two thumbs make a range slider.
Imports
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbInput,
SliderThumbIndicator,
SliderTrack,
useSliderContext,
useSliderThumbContext,
type SliderOrientation,
type SliderProps,
type SliderRangeProps,
type SliderSize,
type SliderThumbProps,
type SliderThumbInputProps,
type SliderThumbIndicatorProps,
type SliderTrackProps,
type SliderVariant,
} from '@vega-ui/react';Exported Types
SliderPropsSliderTrackPropsSliderRangePropsSliderThumbPropsSliderThumbInputPropsSliderThumbIndicatorPropsSliderSizeSliderVariantSliderOrientation
Minimal Composition
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
export default function MinimalComposition() {
return (
<Slider defaultValue={50} style={{ width: '100%', maxWidth: 400 }}>Required Parts
Slider: root, values of all thumbs and shared range settingsSliderThumb: one handle per valueSliderThumbInput: the native range input of a handle
Optional Parts
SliderTrack: the visible railSliderRange: the filled part of the rail, insideSliderTrackSliderThumbIndicator: the visual handle; without it the thumb is invisible
Composition Order
SliderSliderTrack>SliderRangeSliderThumb, one per value,indexin order frommintomax, withSliderThumbInputandSliderThumbIndicatorinside
Variants
- Size:
sm,md,lg - Variant:
primary,secondary - Orientation:
horizontalorvertical - Thumbs: one value or a range of several
- Value model: controlled or uncontrolled on the root, a number for one thumb or an array for several
- Step: numeric step or
'any'
Edge Cases
- Exact values are harder to target with a slider than with typed input.
- Vertical sliders need an explicit height.
- Thumbs cannot pass each other;
minStepsBetweenThumbskeeps a gap between them. - Without
valueordefaultValuethe slider has one thumb in the middle, like<input type="range">.
Common Mistakes
- Using a slider where exact numeric entry is the primary need.
- Forgetting visible value feedback for precision-sensitive flows.
- Leaving thumbs without
aria-labeloraria-labelledby. - Rendering a different number of
SliderThumbs than values, or giving two thumbs the sameindex.
Examples
Basic
Basic: labeled slider with a default value
An uncontrolled slider: defaultValue sets the start and name on the root reaches the thumb input. SliderThumbInput is the native <input type='range'>, so a visible Label points at its id.
import {
Label,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
export default function SliderWithDefaultValue() {
return (Basic: two thumbs for a range
An array defaultValue creates one value per SliderThumb by its index. Each thumb input gets its own name and aria-label, and minStepsBetweenThumbs keeps the shift at least an hour long.
import {
Fieldset,
FieldsetLegend,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
export default function RangeSlider() {Controlled/Stateful
Controlled/Stateful: value driving a preview
value with onChangeValue keeps the number in the parent: the readout and the preview swatch follow it while dragging. aria-valuetext announces the value with its unit.
import { useState } from 'react';
import {
Label,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';
Controlled/Stateful: price filter over a product list
A controlled two-thumb range filters a list as it moves. Prices are formatted once with Intl.NumberFormat and reused for the readout and for aria-valuetext on each thumb.
import { useState } from 'react';
import {
Fieldset,
FieldsetLegend,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';Controlled/Stateful: adding and removing thumbs
The number of thumbs follows the length of the value array: render one SliderThumb per entry. Thumbs stay ordered and minStepsBetweenThumbs apart, and each gets a label from its position.
import { useState } from 'react';
import {
Button,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';
Form/Integration
Form/Integration: reading values with FormData
A range with name on the root submits one entry per thumb, so FormData.getAll('age') returns both bounds; a single thumb is read with FormData.get. Form reset restores defaultValue.
import { FormEvent, useState } from 'react';
import {
Button,
Fieldset,
FieldsetLegend,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,Layout/Overlay
Layout/Overlay: vertical slider
orientation='vertical' grows from the bottom and needs an explicit height. The value is shown under the track, and the keyboard works on both arrow axes.
import { useState } from 'react';
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';
export default function VerticalSlider() {Layout/Overlay: volume slider in a popover
An icon-only trigger opens a Popover with a vertical slider. The trigger's aria-label includes the current value, so it is announced without opening the popover, and the icon follows the value.
import { useState } from 'react';
import {
Icon,
IconButton,
Popover,
PopoverContent,
PopoverTrigger,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,Error
Error: value above a policy limit
The slider allows the full range, but values above the policy limit are invalid: the thumb input gets aria-invalid and aria-describedby pointing at the error, which disappears once the value is back under the limit.
import { useState } from 'react';
import {
HelperText,
Label,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';Disabled
Disabled: locked value and disabled by a fieldset
disabled on the root locks every thumb; the reason is linked with aria-describedby. A slider inside a Fieldset disabled is disabled natively and gets the disabled look as well — here while automatic brightness is on.
import { useState } from 'react';
import {
Fieldset,
FieldsetLegend,
HelperText,
Label,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,Edge
Edge: free precision with step any
step='any' drops the step grid, so the value can be any fraction between min and max. Arrow keys then move by a hundredth of the range; the readout rounds for display.
import { useState } from 'react';
import {
Label,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';
Edge: value text with units and a negative minimum
A range from −10 to 30 with aria-valuetext, so screen readers say “20 °C” instead of a bare number.
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
import { useState } from 'react';
export default function ValueTextForScreenReaders() {
const [temperature, setTemperature] = useState(20);Edge: snapping to datalist markers
A <datalist> connected through list makes the native input snap near its values while dragging. The browser does not draw the marks, so draw your own if they must be visible.
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
export default function MarkersFromADatalist() {
return (
<>Edge: vertical group with a negative range
Five vertical sliders from −12 to +12 dB form an equalizer inside a labelled role='group'. Each thumb is named by its band and announces its gain in dB.
import {
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
Text,
} from '@vega-ui/react';
import { useState } from 'react';
const bands = ['60 Hz', '230 Hz', '910 Hz', '3.6 kHz', '14 kHz'];Anatomy
Overview
Slider holds the values of all thumbs and the shared settings (min, max, step, orientation, disabled, name). Each SliderThumb groups a SliderThumbInput, a native <input type="range"> laid over its part of the track between its neighbours, and a SliderThumbIndicator drawn at its value.
Required Parts
Slider
Required. Passes range settings to the thumbs and keeps neighbouring thumbs apart. A vertical slider needs a height from its parent.
SliderThumb
Required. One handle: index picks its entry of the root value and the position variables are set for its parts.
SliderThumbInput
Required, a direct child of SliderThumb. A controlled native range input: focus, keyboard, form value and accessibility come from the browser; its min and max are the neighbours.
Optional Parts
SliderThumbIndicator
The visual handle, a direct child of SliderThumb. It can hold any content: a value bubble, an icon, an image. It lets the pointer through to the native input under it.
SliderTrack
The visible rail. Without it the thumbs still work over an invisible track.
SliderRange
The filled part of the rail: from min to a single thumb, or between the first and the last thumbs.
Composition Order
SliderSliderTrack>SliderRangeSliderThumb, one per valueSliderThumbInputSliderThumbIndicator
Valid Composition Patterns
import {
Fieldset,
FieldsetLegend,
Slider,
SliderRange,
SliderThumb,
SliderThumbIndicator,
SliderThumbInput,
SliderTrack,
} from '@vega-ui/react';
export default function RangeSlider() {Invalid Composition Patterns
Root without thumbs
The track renders, but there is nothing to interact with or submit.
Thumbs outside the root
SliderThumb reads its settings from the root and is positioned over the root track.
Input or indicator outside SliderThumb
They read their index from SliderThumb; the hover, active, focus and disabled styles of the indicator follow the input of the same SliderThumb.
Vertical slider without a height
The control renders, but the interaction space collapses.