SegmentedControl
iOS-style segmented selector with a sliding indicator.
Installation
npx axiom add segmented-controlpnpm dlx axiom add segmented-controlyarn dlx axiom add segmented-controlbun x axiom add segmented-controlInstalls: react-native-reanimated, react-native-worklets, react-native-gesture-handler.
Selection, measurement and the draggable indicator live in use-segmented-control.ts, shared by every styling variant. Colors come from segmentedControl.default.{default,selected,disabled}.{track,indicator,border,foreground} in the component tokens.
Usage
import { SegmentedControl } from "@/components/ui/segmented-control";
<SegmentedControl
options={["List", "Grid"]}
value={layout}
onValueChange={setLayout}
/>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
options | Array<string | SegmentOption> | — | The segments. A string is used as both value and label. SegmentOption is { value, label?, icon?, accessibilityLabel?, disabled? }. |
value | string | — | Value of the selected segment. |
defaultValue | string | first option | Initial selection when the control manages its own state. |
onValueChange | (value: string) => void | — | Called when the user picks another segment. |
size | 'md' | 'lg' | 'md' | Minimum height: 32 or 40pt. Grows with larger system text. |
fullWidth | boolean | true | Stretches to the parent width with equal segments. false sizes it to its content. |
disabled | boolean | false | Disables the whole control. |
haptic | HapticKind | false | 'selection' | Haptic played when the user changes the segment, by tap or drag. false turns it off. |
style | StyleProp<ViewStyle> | — | Extra styles for the track. |
The indicator slides on the UI thread with Reanimated and can be dragged from one segment to another. Keep it to 2–5 short options: past that, labels get truncated.
Haptics
The control plays a selection haptic when the user changes the segment, by tap or by dragging the indicator. Pressing the segment that is already selected plays nothing. Pass haptic={false} to turn it off, or another kind to change it. Nothing plays until your app connects a haptics library: see Haptics.
Use cases
Switching the view of the same data
The segments change how the content is shown, not what it is. Icons are enough when they are standard.
<SegmentedControl
fullWidth={false}
options={[
{ value: "list", icon: "menu", accessibilityLabel: "List" },
{ value: "grid", icon: "grid", accessibilityLabel: "Grid" },
]}
value={layout}
onValueChange={setLayout}
/>Filtering a list in place
A short list of states above the content. Changing segment filters the list below without navigating.
<SegmentedControl options={['All', 'Active', 'Delivered']} value={status} onValueChange={setStatus} />
<FlatList data={orders.filter(byStatus(status))} renderItem={renderOrder} />Setting with few options
A compact alternative to radios for 2–3 values that the user compares at a glance.
<SegmentedControl
size="lg"
options={[
{ value: "light", label: "Light", icon: "sun" },
{ value: "dark", label: "Dark", icon: "moon" },
{ value: "system", label: "Auto" },
]}
value={scheme}
onValueChange={setScheme}
/>Related
- Tab, for switching between content areas
- ButtonGroup
- Radio