Segmented Control
A row of segments that switches between a few short options, like a view or an environment. A raised thumb slides to the checked segment.
When to use
- Switch between a few short options, like a view or an environment, in one row.
- Prefer
RadioGroupfor a form field whose options need a description, or stack in a column. - Prefer
Tabswhen each option shows its own panel of content. - Prefer
Selectwhen the set is long, or the row has little space.
Controlled
Pass value and onChange to keep the checked segment in your own state. The control reports the new value on a click, a key, and a drag.
Current view: list
Icon segments
A segment can hold only an icon. Give each one its name in sr-only text, so a screen reader announces it.
With TanStack Form
Use @tanstack/react-form with zod to keep the control controlled in a form. Pass the field's name, value, and handleChange. Use Field.Set and Field.Legend to name the group and show its errors.
Composition
Radio semantics
SegmentedControl is a radio group underneath. It shares its primitive with RadioGroup, so it has the same contract: role="radiogroup", one tab stop, arrow keys that move the checked segment, and a hidden <input type="radio"> for form submission when it has a name.
To change the value, click a segment, use the arrow keys, or drag the thumb with a mouse or a finger.
Dragging the thumb
A sideways drag on the checked segment moves the thumb with the pointer. On release, the thumb slides to the nearest enabled segment, and that segment becomes checked. A flick carries the thumb further. Past either end, the thumb meets resistance and stays inside the track. A drag that goes up or down more than sideways does not start, so the page still scrolls on a touch screen.
The thumb slides on every change: a click, a key, a drag, or a new value. With reduced motion, it moves at once.
API Reference
SegmentedControl.Root
The row of segments. It renders the radio group itself, so use it in place of RadioGroup.Root, never inside one.
All props from Headless UI RadioGroup, including:
SegmentedControl.Item
One segment. It grows to share the row and keeps its label on one line, so keep labels to one or two words. Inside Field.Control, the segment picks up aria-invalid, aria-errormessage, and aria-describedby.