Segmented Control
A single-select group of segments for switching between a small, fixed set of views or options.
Usage
A row of segments where exactly one is selected. A thumb slides to the active segment. Use it for a small, fixed set of mutually exclusive options that fit on one line, such as a chart period or a view mode.
The control fills its container and the segments share the width equally. Put it in a width-constrained wrapper to make it narrower.
import {
SegmentedControl,
SegmentedControlItem,
} from '@epilot/spark-ui/segmented-control'function PeriodPicker() {
return (
<SegmentedControl
aria-label="Period"
value={period}
onValueChange={setPeriod}
>
<SegmentedControlItem value="day">Day</SegmentedControlItem>
<SegmentedControlItem value="week">Week</SegmentedControlItem>
<SegmentedControlItem value="month">Month</SegmentedControlItem>
</SegmentedControl>
)
}Reach for a segmented control when the options are few (two to five) and worth
keeping visible at all times. For switching between panels of page content use
Tabs. For a longer list, richer option cards, or
options that wrap, use Radio Card Group.
For a single on and off state use Switch. This
component replaces the deprecated pill variant of Tabs.
Examples
Styles
styleVariant sets both the track chrome and the selected segment. solid and
soft sit in a filled groove; surface adds a bordered, faintly-filled track;
outline is a bare outline. The selected segment fills with the accent for
solid, and is a raised neutral surface for the rest (differing by border).
Sizes
size sets the height and label typography. Use small in toolbars and dense
layouts, medium for prominent, touch-first controls.
With icons
Put a MaterialSymbol glyph before the label inside the segment. It inherits the
segment's text color (so it turns with the active state) and scales with size.
Use the bare glyph here, not the boxed Icon display component. An icon-only
segment needs an aria-label so it still has an accessible name.
Disabled segment
Set disabled on a single segment to block it while the rest stay usable. The
segment keeps its place and grays out.
API Reference
SegmentedControl
Renders Base UI Tabs as a value
selector (no content panels). The selected segment reads the shared
--spark-style-* tokens, so its look tracks the theme like the other controls.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled selected value. Provide onValueChange to update it. |
defaultValue | string | — | Initial selected value when uncontrolled. Set one so a segment is active on mount. |
onValueChange | (value: string, details) => void | — | Fires when the selection changes. |
styleVariant | "solid" | "soft" | "surface" | "outline" | "solid" | Sets the track chrome (filled groove, bordered surface, or bare outline) and the selected segment (accent fill for solid, raised neutral surface otherwise). |
size | "small" | "default" | "medium" | "default" | Control height, padding, and label typography. Matches the Button size scale. |
aria-label | string | — | Names the group. Lands on the role="tablist" track, not the outer element. |
className | string | — | Merges onto the track (the visible container). |
SegmentedControlItem
One segment. Renders a Base UI Tabs.Tab.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. The value this segment selects. |
disabled | boolean | false | Blocks this segment while the others stay usable. |
className | string | — | Merges onto the segment. |
Accessibility
- The track is a
role="tablist"and each segment arole="tab", with the active segment markedaria-selected. Always passaria-labeloraria-labelledbyso the group has a name. - Arrow keys move between segments and
HomeandEndjump to the first and last. Activation is manual: the focused segment is selected onEnterorSpace, or on click. - A disabled segment stays focusable and surfaces
aria-disabledso assistive tech can announce it. - The thumb slide is suppressed under
prefers-reduced-motion. - Give an icon-only segment an
aria-label; a segment with a visible label needs nothing extra.