SegmentedControl
SegmentedControl is a controlled radiogroup for one choice in a small, visible set. Choose it
when selection changes the current view or mode, not when people are navigating elsewhere.
Examples
Choosing a range
value and onChange make the current choice explicit in your state. The selected option is the
group's one Tab stop, even though every option remains clickable.
Skipping unavailable choices
Disabled options stay visible when their absence would be surprising. Arrow keys, Home and End skip them rather than trapping focus on an unavailable choice.
When to use
Use SegmentedControl for a single choice from a handful of visible options, such as a project view or time range. Keep the labels short enough that people can compare them without scrolling.
Reach for something else when:
- A form field needs labels, help text or a group description — use Radio.
- Each choice navigates to a peer view or URL — use Tabs.
- The choice is a boolean setting — use Switch.
Accessibility
- Renders
role="radiogroup"with a consumer-provided accessiblelabel; each option is arole="radio"witharia-checked. - It has one Tab stop through roving
tabIndex. Arrow keys move focus and select, while Home and End move to and select the first and last enabled options. - Disabled options are not focusable and are skipped by every keyboard movement. Keep a visible explanation nearby when the unavailable state is not self-evident.
- Pointer clicks follow the same
onChangepath as the keyboard. Keepvaluecurrent after every callback, or the announced selection and visible state will disagree.
Props
| Name | Type | Required | Description |
|---|---|---|---|
options | SegmentedControlOption[] | Required | Options rendered in keyboard-navigation order. Provide at least two options. |
value | string | Required | Currently selected option value. |
onChange | (value: string) => void | Required | Called with the next value after pointer or keyboard selection. |
label | string | Required | Translated accessible name for the radiogroup. |
Plain HTML
The native buttons carry radio semantics. Only the selected, enabled option belongs in the Tab order:
<div class="lyra-segmented" role="radiogroup" aria-label="Project view">
<button
class="lyra-segmented__option lyra-segmented__option--active"
type="button"
role="radio"
aria-checked="true"
tabindex="0"
>
List
</button>
<button
class="lyra-segmented__option"
type="button"
role="radio"
aria-checked="false"
tabindex="-1"
disabled
>
Board
</button>
<button
class="lyra-segmented__option"
type="button"
role="radio"
aria-checked="false"
tabindex="-1"
>
Calendar
</button>
</div>