Forms
Slider
A value chosen along a range.
Usage
import { Slider } from '@misoto22/design'Notes
A value chosen along a range.
Radix owns the keyboard contract — arrows step, Page keys jump, Home and End reach the ends — and the ARIA that reports the value. What is here is the look, and the labelling, which is the part a slider most often gets wrong: a thumb that announces "42" and nothing else leaves a screen reader user with a number and no idea what it measures.
A 44px hit area sits invisibly around the 16px thumb, because a thumb sized for the design is well under any pointer-target guideline.
editable is the answer to the thing a slider cannot do. Reach for it whenever the exact figure is the point — a budget, a timeout, a price — and leave it off when the value is genuinely approximate, because a box invites precision the setting may not have.
Inside a Field, the hint, the error and the requirement land on the THUMB, which is the element carrying role="slider" — on the root they would sit on a <span> with no role and announce nothing. The NAME still comes from label here: a field's label above a slider points at that same roleless root, so it neither names the control nor clicks through to it.
Anatomy
| Element | Description |
|---|---|
| Trackrequired | A 1px rule in --stone that thickens to 1.5 when the pointer is anywhere over the control, not only over the thumb. |
| Range | The --accent fill from the minimum to the thumb, or between the two thumbs of a range. |
| Thumb | One per entry in the value array — so the number of thumbs comes from the value, not from a prop, and a slider given neither value nor defaultValue falls back to the primitive’s own default of one thumb at the minimum. Each is a 16px circle with an invisible 44px hit area from a before pseudo-element. |
| Value readout | Only with showValue: a mono row above the track, the names on the start edge and the formatted values on the end, each joined by an en dash and in the thumbs’ own order — so a two-ended range reads “Minimum – Maximum” over “10 – 90”. |
| Editable readout | What editable turns those figures into: one box per thumb, showing format’s output at rest and the bare number while it has focus, so a reader still sees “$1,200” and a typist is never asked to type a currency symbol back. Each is named separately from its thumb — two controls announcing “Quality” is one control announced twice. |
Best practices
Do
- Pass defaultValue or value whenever there is more than one end to it. The thumb count comes from that array, so a price filter left to the default is a single thumb sitting at the minimum.
- Pass an array of two names for a two-thumb range: every thumb after the first falls back to names[0], so both ends of a price filter otherwise announce themselves as “Minimum”.
- Turn on editable when the exact number matters. A slider on its own cannot be typed into, and someone who needs 37 rather than roughly 40 is dragging a 16px thumb across a hundred steps to get it — the box in the readout is the way out, and it replaces the second Input this used to ask for.
Don’t
- format becomes each thumb’s aria-valuetext, which REPLACES the number rather than decorating it — so a formatter that rounds hard or drops the unit is what a screen reader gets instead of the value.
- editable typing is bounded by the NEIGHBOURING thumb as well as by min and max, and it has to be: 90 typed into the lower end of a range sitting at 70 would otherwise cross the two thumbs over. So a number can be accepted and then land somewhere else, and the box shows where it landed.
- Do not disable a slider to make it read-only: the whole control dims and stops taking the pointer, and Radix drops the thumb out of the tab order, so the value becomes unreachable rather than uneditable.
- Do not pass two names to a one-thumb slider: the heading prints one name per THUMB, so the second is drawn nowhere and announced nowhere.
- A Field’s label above it does not name it and does not click through: the role is on the THUMB and the root is a <span>, so the label prop here is the only name a reader hears. The hint and the error do reach the thumb.
Examples
default
One value, then two, both with the readout on. Always pass defaultValue or value: the thumbs are rendered from this component's own array rather than from Radix's default, so a Slider given neither draws a track with nothing on it to drag. A two-thumb range needs two names — every thumb after the first falls back to the first name, and both ends of a price filter otherwise announce themselves as Minimum. The heading above the numbers prints that first name only, so read it as the start of the pair rather than as a label for both.
typing the exact value
A slider is a control for a neighbourhood, and this is the way out of it. Somebody who needs 1,150 rather than roughly 1,200 was previously dragging a 16px thumb across a hundred steps to get there, or was given a second input beside the track that had to be kept in step by hand; editable puts the box where the number already was. It shows format's output at rest and the bare number while it has focus, so a reader still sees $1,200 and a typist is never asked to type a currency symbol back. On a range, each end gets its own box and each is held inside the other — typing 90 into the lower end of a range sitting at 70 lands on 70, because the two thumbs cannot cross.
naming the unit
format prints, and nothing more: it renders the readout above the track, and nothing here sets aria-valuetext, so a thumb showing 12s announces the bare number 12. The unit belongs in the name, which is announced — “Request timeout in seconds”, read together with 12, is a fact, while “Timeout” read with 12 is a riddle. The second slider carries no format at all, which is what a plain count should look like.
Keyboard
| Key | Does |
|---|---|
| ←→ | Moves by one step. |
| Page UpPage Down | Moves by a larger step. |
| HomeEnd | Jumps to the minimum or maximum. |
Accessibility
- label is required. A thumb that announces "42" and nothing else leaves a screen reader user with a number and no idea what it measures.
- A 44px hit area sits invisibly around the 16px thumb.
- format is announced as aria-valuetext, so a thumb showing “$1,200” says that rather than 1200.
- Arrows step, Page keys jump, Home and End reach the ends.