Segmented Control
A Segmented Control allows users to choose one of a few options that are displayed side by side on a track.
When to Use
- to change what one view shows, such as the period of a chart: “6 months” or “12 months”
- for a setting that keeps one option selected
- for options that fit in one row
When Not to Use
- for views that each have their own content (use Tabs)
- for options where none or several can be on (use a Toggle Group)
- for a choice that is submitted with a form (use a Radio Group)
- for more options than fit in a row (use a Select)
| Segmented Control | Toggle Group | Tabs | |
|---|---|---|---|
| Purpose | One setting of a view | Options that are each on or off | Views that each have a panel |
| Options On | One | None, one, or several with multiple | One |
| Roles | group of buttons with aria-pressed | group of buttons with aria-pressed | tablist, tab, and tabpanel |
| Arrow Keys | Move focus | Move focus | Move focus |
Enter or Space | Selects the option | Turns the item on or off | Shows the tab’s panel |
| Mark | An indicator that slides | A muted tint and a mark that the product adds | An indicator that slides, as a tile or a line |
| Sizes | sm, default, and lg | sm, default, and lg | One, 32px tall |
| Orientation | Horizontal | Horizontal or vertical | Horizontal or vertical |
Anatomy
| Element | Usage |
|---|---|
| Option | Required |
| Track | Required |
| Indicator | Selected option only |
One indicator slides to the selected option.
Sizes
A Segmented Control has the sm, default, and lg sizes. It is as tall as a Button of the same size, so the two line up in a row. See Sizing for where to use each height.
Behavior
SegmentedControl is built on Base UI’s Toggle Group. It keeps one option selected and moves one indicator to it.
Selection
When users click the selected option, nothing happens because SegmentedControl cancels a change that would result in an empty value. The value is an array that contains one string, as in Base UI’s Toggle Group.
Set defaultValue or value. If neither is set, no option is selected, and the indicator doesn’t appear until users click an option.
Width
The track is as wide as its options, and it doesn’t wrap or scroll. An option doesn’t shrink, and its label doesn’t wrap, so a set that is wider than its container overflows the container’s edge.
Content
| String | Rule | Example | Counterexample |
|---|---|---|---|
| Option | One or two words that name the choice, not an action | “Month” | “Show by month” |
aria-label | Name what the options set | “Period” | “Options” |
Accessibility
A Segmented Control is a group of buttons with aria-pressed, not a radiogroup or a tablist, so the arrow keys move focus and don’t select. Users press Home or End to move focus to the first or the last option, and Enter or Space to select the focused option.
A Segmented Control needs a name because options like “Week”, “Month”, and “Year” don’t tell screen reader users what they set. To provide one, set aria-label, or point aria-labelledby at a visible label.
Installation
npx shadcn@latest add @summit/segmented-controlThe CLI also adds @summit/toggle.
Usage
import { SegmentedControl, SegmentedControlItem } from '@/components/ui/segmented-control';
<SegmentedControl defaultValue={['month']} aria-label="Period">
<SegmentedControlItem value="week">Week</SegmentedControlItem>
<SegmentedControlItem value="month">Month</SegmentedControlItem>
<SegmentedControlItem value="year">Year</SegmentedControlItem>
</SegmentedControl>;API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'default' | 'sm' | 'lg' | 'default' | The height of the track and the text size of the options |
Other props are passed to Base UI’s Toggle Group, except multiple and orientation, which SegmentedControl doesn’t accept. See the Base UI Toggle Group documentation for value, defaultValue, onValueChange, and disabled. SegmentedControlItem adds no props to Base UI’s Toggle. See the Base UI Toggle documentation for value.