SegmentedControl
SegmentedControl is used to pick one choice from a linear set of closely related choices, and immediately apply that selection.
Page navigation navigation
A SegmentedControl is treated like a list where each list item contains a button.
Do not treat a SegmentedControl like any of the following ARIA roles:
radiogrouprequires a save button to apply changes.tablistis used to switch between tab panels.toolbaris a collection of function buttons.
These roles have different keyboard rules and may confuse assistive tech users if used for SegmentedControls.
Keyboard navigation
Tab
Tab navigates through focusable elements. When entering the control:
- Focus goes to the first button if coming from before the control.
- Focus goes to the last button if coming from after the control.
Enter or Space
Selects a focused, unselected button. Pressing again on a selected button does nothing.
Arrow Left or Arrow Right
Arrow keys don't change focus or selection, unlike in radio groups or toolbars.
Accessibility and usability expectations
SegmentedControl provides people with the ability to select a choice from a small, focused group, and immediately activate the selected option.
Presentation
Cognition
- Each
SegmentedControlsegment has a clear and succinct label (using a noun or short phrase) that informs users as to the purpose of the control - When icon-only segments are used, ensure that they have a clear label that conveys equivalent information
- There must be a visual cue for the selected segment
Vision
- When using icons, ensure that they have at least a color contrast ratio of 3:1 against the segment’s default and selected states
- Ensure that text has a color contrast ratio of at least 4.5:1
Mobility
- Segments must have a minimum target size of 24×24 CSS pixels. This is to ensure that the button is large enough to be easily activated by users with moving disabilities. The entire touch area should respond to taps, clicks, and hovers even if it isn't directly on the control.
Edit in FigmaAdaptability
- Make sure that text can be increased up to 200%, and any visible labels remain visible
- Segments must remain readable and not require horizontal scrolling to read or operate them, at a viewport size of 320 by 256 CSS pixels
- When adding additional text spacing, make sure that visible labels can still be read in their entirety
Interaction
Keyboard
- Each segment must receive focus when navigating with the
Tabkey EnterorSpacemust select the segment- Segments must receive focus in a logical order, which in the majority of cases, will be the order that they are visually displayed
Touch and mouse
- Segments must be activated on the up event, and not the down event, or there must be a way to prevent the action from taking place on the down event
Engineering for compatibility with assistive technology
Screen reader
- The order in which the segments are implemented should result in a logical reading order
- A group of segments must have an accessible name, to provide people with context as to what they’re choosing and why
- Segments that feature an icon and visible label should only use the visible label text in their accessible name
- Segments labelled using only an icon must have an accessible name, which you can add with the
aria-labelprop - Segments must programmatically convey when they are selected
- If used to complete an action on the same page, without changing the URL, the segmented control button must have a
roleofbutton, to help convey how people can interact with it - If used to navigate to a different page, changing the URL, the segmented control button must have a
roleoflink, to help convey how people can interact with it- If using a link, ensure that the control is labelled consistently across different pages
Speech recognition
- Segments that have a visible label, or associated tooltip, must have an accessible name that includes that content (ideally at the start of the accessible name)
Built-in accessibility features
This component is rendered as an unordered list element (<ul>), with each segment rendered inside a list item element (<li>). This helps to programmatically convey the grouping of the buttons to people who cannot see them.
<ul …>
<li …>
<button aria-current="true" …>… Preview …</button>
</li>
<li …>
<button aria-current="false" …>… Raw …</button>
</li>
<li …>
<button aria-current="false" …>… Blame …</button>
</li>
</ul>
When selected, each segment (rendered as a button) conveys its state using aria-current=“true”. Screen readers will announce this information, to help people understand which of the segments are active.
Implementation requirements
Group label
The SegmentedControl component must be given a group label to help convey the purpose of the grouping, and provide context as to what it relates to.
This can be achieved in a few different ways:
- If there’s already a visible label that relates to the
SegmentedControlcomponent, use thearia-labelledbyprop to reference theidof the visible label, providing the component with an accessible name that matches the label's content. For example:
<label id="sort-by-label" …>Sort by</label>
<SegmentedControl aria-labelledby="sort-by-label" …>
<SegmentedControl.Button defaultSelected>New</SegmentedControl.Button>
<SegmentedControl.Button>Top</SegmentedControl.Button>
</SegmentedControl>
- If there isn’t a visible label, use the
aria-labelprop to provide the group with a name, as demonstrated in the following example:
<SegmentedControl aria-label="File view">
<SegmentedControl.Button defaultSelected>Preview</SegmentedControl.Button>
<SegmentedControl.Button>Raw</SegmentedControl.Button>
<SegmentedControl.Button>Blame</SegmentedControl.Button>
</SegmentedControl>
Button labels
Similar to the aria-label provided for the group, when using icons in a segment, an aria-label must be used to provide the control with an accessible name.
If the button contains an icon and visible label, the aria-label prop must repeat the visible label text.
<SegmentedControl aria-label="File view">
<SegmentedControl.Button defaultSelected aria-label="Preview" leadingIcon={EyeIcon}>
Preview
</SegmentedControl.Button>
…
If the button contains only an icon, the aria-label prop must provide equivalent information, as that conveyed by the use of the icon.
<SegmentedControl aria-label="File view">
<SegmentedControl.IconButton defaultSelected aria-label="Preview" icon={EyeIcon} />
…
How to test the component
Integration tests
- If the
SegmentedControl's segments are visible at wide viewports, ensure they are not hidden at narrow viewports - If the
SegmentedControldynamically adds content to the page, focus management is implemented so that keyboard users can efficiently navigate to the new content and screen reader users don't miss any new content - If the
SegmentedControlis used for regular page navigation/reloading, no focus management is implemented
Component tests
- The
SegmentedControlcomponent is exposed as an unordered list element (<ul>) with an appropriate accessible name - Each
SegmentedControlsegment is exposed as either abuttonorlink, with an appropriate accessible name, wrapped in a list item element (<li>) - Where a segment has a leading icon, it uses an
aria-labelwhich matches the visible label text - The selected segment has an
aria-current=“true”attribute - The component’s buttons remain readable and do not require horizontal scrolling when resized or zoomed to a viewport of 320px
- Each
SegmentedControlbutton meets the minimum target size requirement of 24 by 24 CSS pixels SegmentedControlcomponents do not have more than 2-5 choices, or 6 icon-only segments