A slider sets a number by dragging. Pass one number and you get one thumb; pass two in an array and the same component renders a range. It is built on react-aria’s slider, which is where the keyboard, the value announcements and the number formatting come from.
Anatomy
Section titled “Anatomy”-
Minimum label (optional) the bottom of the range, from01000100minLabel. Drawn only withshowLabels. -
Track the rail the thumb travels. The filled part is not a separate element; the rail is a gradient with a color stop at the current value, and01000100track={false}flattens it. -
Thumb the handle, and the only part that moves. Its position is the value; the tooltip that names the number appears while the thumb is focused or held.01000100 -
Maximum label (optional) the top of the range, from01000100maxLabel.
When to use
Section titled “When to use”A slider cannot be typed into, read at rest, or copied out of. What it can do is change the value while the reader drags it, so they can stop when the result looks right and never find out what “68” meant. That trade is the only reason to reach for one.
Where the number itself is the answer, a text input wins on all three counts a slider loses. A Select or Radio Buttons beat it for a small set of discrete values, which a slider makes fiddly to hit. And a value nobody can change should not be in one at all: a thumb on a track is an invitation to drag it.
Pass an array to get a range
Section titled “Pass an array to get a range”value and defaultValue take a number or an array of numbers, and the length
of the array is the number of thumbs. onChange hands back the shape you passed
in, so a single-value slider gets a number rather than an array of one.
The value is only on screen while the thumb is held
Section titled “The value is only on screen while the thumb is held”The tooltip above the thumb is the only readout, and it is there while the thumb
has focus or is being pressed, closing about half a second after the reader lets
go. hideTooltips removes it entirely, and nothing renders the value at rest.
So if the number has to stay on screen, put it there yourself, beside the slider. A reader comparing a threshold against a figure elsewhere on the page cannot hold a value that vanishes when they look away.
Format the number once, with formatOptions
Section titled “Format the number once, with formatOptions”formatOptions takes Intl.NumberFormat options, and the string it produces is
both the tooltip’s text and the aria-valuetext a screen reader reads out. A
currency or a unit set here is announced as well as shown, where the same
formatting done by hand in a label leaves the announcement as a bare number.
Choose the step before the range
Section titled “Choose the step before the range”step sets which values the reader can reach, and it defaults to 1 on a range
of 0 to 100. On the default 300px track that puts the hundred reachable values
three pixels apart, which a drag can hit.
Widen the range without widening the step and that stops being true. Zero to a thousand in steps of one puts more than three values in every pixel, so the thumb cannot be landed on a number the reader picked. Pick the step the drag can hit, and let the range follow.
Draw the endpoints, or the range is a guess
Section titled “Draw the endpoints, or the range is a guess”showLabels renders minLabel and maxLabel, which fall back to min and
max. Both take any node, so the unit belongs here. Without showLabels
neither renders, and a bare track with no tooltip showing says nothing at all
about what it spans.
Fill the track unless the value has no low-to-high meaning
Section titled “Fill the track unless the value has no low-to-high meaning”The rail paints the part below the value in the accent color, as a gradient stop
rather than a second element. It is the only thing that reports the value when
the tooltip is closed, which is most of the time. track={false} replaces it
with a plain rail, and is for the case where the value has no low-to-high
meaning to fill toward.
width defaults to 300px. Pass auto and the slider takes the width of its
container, which is what a slider in a form wants.
Accessibility
Section titled “Accessibility”A slider’s visible label is not its accessible name
Section titled “A slider’s visible label is not its accessible name”A slider’s accessible name comes from aria-label or aria-labelledby and
nowhere else. The visible label above it belongs to
FormField, and Slider does not read FormField’s
context, so that label is not yet the slider’s name. Give
FormField an inputId and hand the slider an aria-labelledby of the same id
with -label appended.
Nothing in the API names a thumb. Both thumbs of a range slider take the slider’s own name, so a screen reader announces the same label twice and distinguishes the two only by their values. There is no prop to fix it, and “Minimum price” and “Maximum price” cannot currently be reached from this component.
Each thumb is a visually hidden range input, which is where arrow keys, Home and End come from, and what makes the value announceable at all.
Content
Section titled “Content”Carry the unit with the value
Section titled “Carry the unit with the value”The label names what changes, formatOptions carries the unit into both the
tooltip and the announcement, and minLabel and maxLabel carry the bounds. A
label reading “Opacity” above a tooltip reading “34%” tells the reader more than
“Opacity (%)” above a bare “34”.
Say what a legal choice will cost
Section titled “Say what a legal choice will cost”A slider clamps to its own range, so it cannot produce a value that is out of bounds or the wrong type. An error under one is always about the consequence of a legal choice, which means it has something to say: not “enter a valid number”, but what a threshold this low will do.
| Name | Type |
|---|---|
min |
|
minLabel |
|
max |
|
maxLabel |
|
onChange |
|
value |
|
defaultValue |
|
step |
|
showLabels |
Show labels on ends of track |
track |
Track style |
hideTooltips |
Hide tooltips on slider thumbs |
width |
|
disabled |
|
formatOptions |
|
id |
|
className |
|
name |
|
onBlur |
|
aria-label |
|
aria-labelledby |
|
Was this page helpful?