Segmented control
StableA pill track for choosing one of a few views: the date range of a chart, a grid or a list, a device to preview on. The chosen option rides a raised thumb that glides between them.
Playground
Change the props, then click between the options to watch the thumb glide.
<SegmentedControl
aria-label="Preview size"
options={[
{ value: 'desktop', label: 'Desktop', icon: <DesktopIcon /> },
{ value: 'tablet', label: 'Tablet', icon: <DeviceTabletIcon /> },
{ value: 'phone', label: 'Phone', icon: <DeviceMobileIcon /> },
]}
/>A date range for a chart
The most common job: pick the period, and the figure and chart change in place. Control it with value and onValueChange. Typed options keep the value typed too.
Takings£13,517.77
Sizes
md is 36px tall (default) and sm 30px, the same heights as buttons. Labels are 13px and 12px; icons 15px and 13px.
Full width
fullWidth stretches the track and shares it equally between the options. Use it in dialogs, popovers and narrow panels, where the control is the width of the fields around it.
The control has no visible label of its own and cannot sit in a Field. For a visible label, write it above and point aria-labelledby at it, in place of aria-label. A hint below can be linked with aria-describedby.
Access
Orders, customers and fulfilment. No settings.
With icons
A leading icon on each option, for views that have a well-known picture.
Icon only
Set iconOnly on an option and keep its label: the icon is centred and the label becomes what screen readers say. Options cannot carry tooltips, so only drop the words when every icon is unmistakable, like text alignment in the page builder.
Disabled
An option with disabled: true drops to 45%, cannot be chosen and is skipped by the arrow keys. Say nearby why it is off. disabled on the control turns off every option.
Keyboard
It behaves as a radio group: one Tab stop, and the arrows move the choice.
| Key | What it does |
|---|---|
| Tab | Moves focus to the chosen option. The whole control is one Tab stop. |
| Right and down arrows | Choose the next option, skipping disabled ones, and wrap round from the last to the first. |
| Left and up arrows | Choose the previous option, the same way. Left and right swap in right-to-left layouts. |
| Home, End | Choose the first or the last enabled option. |
The gliding thumb
There is one thumb, and it moves: a raised pill (white in light, a step lighter than the track in dark) that glides to the new choice on the snappy spring. The chosen label turns semibold without changing width, because an invisible semibold copy of the text holds the space.
Under reduced motion the thumb jumps straight to the new option, and only the text colour fades. Click along the options, or use the arrow keys.
In both themes
Text, icons and icon only, light and dark side by side. In dark the thumb is a lighter step of the track.
Guidelines
- Two to five options, one or two words each. With more, or with long names, use a menu.
- It changes what is on screen straight away and never waits for a Save button.
- Keep the options in a natural order, such as shortest period to longest, and start on the one people use most.
- Drop the words only when every icon is unmistakable, and keep a hidden label on each.
Accessibility
- A
radiogroupnamed by the requiredaria-label, with each option aradiobutton carryingaria-checked. - One Tab stop: focus lands on the chosen option, and the arrow keys move and choose together.
- Disabled options are native disabled and skipped by the arrows.
disabledon the control also setsaria-disabledon the group. - Icons are hidden from assistive tech, so an icon-only option needs its hidden text label.
- The focus ring is teal, 2px, just outside the option, for keyboard focus only.
- Under reduced motion the thumb jumps instead of gliding.
Props
Other attributes, such as aria-describedby, go to the group.
SegmentedControl
| Prop | Type | Default | Description |
|---|---|---|---|
optionsRequired | SegmentedControlOption<V>[] | None | The choices, in order. See Option below. |
aria-label | string | None | Names the group, e.g. "Date range". Give this or aria-labelledby: the control has no visible label. |
aria-labelledby | string | None | The id of a visible heading that names the group, in place of aria-label. |
value | V | None | The chosen value, when you control it. |
defaultValue | V | None | The starting value when uncontrolled. Defaults to the first enabled option. |
onValueChange | (value: V) => void | None | Called when the choice changes, by click or by arrow key. |
size | 'sm' | 'md' | 'md' | 30 or 36px tall. |
fullWidth | boolean | false | Stretch to the container, options sharing the width equally. |
disabled | boolean | false | Turns off every option. |
Option
| Prop | Type | Default | Description |
|---|---|---|---|
valueRequired | V | None | A string. What onValueChange reports. |
labelRequired | ReactNode | None | The words. With iconOnly, what screen readers say. |
icon | ReactNode | None | Leading icon: 15px, or 13px at sm. |
iconOnly | boolean | false | Show the icon alone, centred on a round thumb. Needs an icon. |
disabled | boolean | None | Cannot be chosen; skipped by the arrow keys. |