suiss/ui · Pattern
Segment Picker
A segmented control for one exclusive choice that becomes a native select on mobile.
Segment Picker is an open-source pattern from suiss/ui for React. The @esuiss/ui CLI copies its source into your project, so you own the code.
SegmentPicker presents a small set of mutually exclusive options, such as a time period or a view mode. On desktop it renders a suiss/ui ToggleGroup in which exactly one segment stays pressed; clicking the pressed segment keeps it selected. On mobile (below 48rem, via useIsMobile) it renders a NativeSelect so the choice fits narrow screens and uses the platform picker.
Each SegmentPickerItem becomes a toggle on desktop and an option on mobile. Use it for two to five short options that change how content is displayed.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
-
Add the pieces it builds on: Native Select, Toggle Group,
use-mobile. -
Copy the source into
components/patterns/segment-picker.tsx:
- Update the import paths to match your project.
Usage
- The value is uncontrolled by default; use
defaultValue, orvaluewithonValueChangeto control it.onValueChangefires only when the selection changes. - Without a value, no segment is pressed and the mobile select shows an empty disabled option.
- On mobile each option shows
label, thenaria-label, then string children, thenvalue. Give icon-only segments anaria-label, and segments with mixed content alabel. variantandspacingapply only on desktop. On mobile,lgfalls back to the default size.- With
name, desktop renders a hidden input so the value is submitted with a form.
Examples
Without value
Starts with no segment pressed.
Outline
Uses the outline variant.
Spaced
Separates the segments with spacing.
Sizes
Shows the sm, default and lg sizes.
With icons
Uses icon-only segments named by aria-label.
With icons and text
Combines icons and text, with label for the mobile option text.
Disabled item
Disables a single segment.
Disabled
Disables every segment.
Controlled
Owns the value in state with value and onValueChange.
API Reference
SegmentPicker
The root that renders the toggle group or native select and holds the value.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The selected value when controlled. |
defaultValue | string | - | The initially selected value when uncontrolled. |
onValueChange | (value: string) => void | - | Called with the new value when the user selects a different segment. |
variant | "default" | "outline" | "default" | The visual style of the desktop segments. |
size | "sm" | "default" | "lg" | "default" | The control size; lg maps to the default size on mobile. |
spacing | number | 0 | The gap between desktop segments; 0 joins them. |
id | string | - | The ID of the group on desktop or the select on mobile. |
name | string | - | The field name submitted with a form. |
disabled | boolean | - | Disables every segment. |
className | string | - | Classes applied to the group on desktop or the select on mobile. |
children | React.ReactNode | - | The SegmentPickerItem elements. |
aria-label | string | - | The accessible name of the control. |
aria-describedby | string | - | The ID of an element that describes the control. |
SegmentPickerItem
One option, rendered as a toggle on desktop and an option on mobile.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | Required | The value selected by this segment. |
label | string | - | Text for the mobile option, and the desktop content when there are no children. |
disabled | boolean | - | Prevents selecting this segment. |
className | string | - | Classes applied to the desktop toggle. |
children | React.ReactNode | - | The desktop segment content, such as text or an icon. |
aria-label | string | - | The accessible name of the segment, also used as mobile option text. |
Accessibility
- On desktop the root is a
groupnamed byaria-label, and each segment is a button witharia-pressed. - Disabled segments are disabled buttons and cannot be selected.
- On mobile the control is a native
select.
Notes
Styling hooks: data-slot="segment-picker" and segment-picker-item. SegmentPickerItem throws when used outside SegmentPicker.