# Segmented control

> Two to five views of the same thing with an elastic highlight that stretches toward the new segment, can be dragged, and ticks at every boundary. Includes a billing toggle.

- Type: Component (inputs)
- Access: Free, open source (MIT)
- Page: https://goodui.dev/native/components/segmented-control
- Markdown: https://goodui.dev/native/components/segmented-control.md
- Registry item: https://goodui.dev/native/r/segmented-control.json
- Dependencies: react-native-gesture-handler, react-native-reanimated
- Keywords: react native segmented control, tabs pill, monthly yearly toggle, billing toggle, pricing switch, animated segmented control

## When to use

- Switching between two to five views of the same data: day, week, month.
- A monthly and yearly price switch on a paywall, with a savings badge.

## When not to use

- Navigation between screens: use tabs.
- More than five options or long labels: use a picker or a list.
- An on or off setting: use a switch.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add https://goodui.dev/native/r/segmented-control.json
npx expo install --fix
```

The component lands in `components/goodui-native/segmented-control/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs locale.

### Setup

- Wrap the app in GestureHandlerRootView and ThemeProvider.

Built-in strings follow `<GooduiLocaleProvider>` (one [language pack](https://goodui.dev/native/r/locale-tr.json) translates the whole kit); the `labels` prop overrides them for one instance.

## Usage

```tsx
import { SegmentedControl, BillingToggle } from "@/components/goodui-native/segmented-control/segmented-control";

<SegmentedControl
  accessibilityLabel="Range"
  value={range}
  onValueChange={setRange}
  options={[
    { value: "day", label: "Day" },
    { value: "week", label: "Week" },
    { value: "month", label: "Month" },
  ]}
/>

<BillingToggle value={period} onValueChange={setPeriod} savings="Save 33%" />
```

## API reference

### SegmentedControl

`import { SegmentedControl } from "@/components/goodui-native/segmented-control/segmented-control";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` (required) | `SegmentedOption<T>[]` | – | Two to five options. Each has a value, a label and an optional badge. |
| `value` (required) | `T` | – | The selected option value. |
| `onValueChange` (required) | `(value: T) => void` | – | Called with the new value on tap, or on release after a drag. |
| `size` | `"sm" \| "md"` | `"md"` | `md` is 40 pt tall, `sm` 32 pt. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |
| `accessibilityLabel` | `string` | – | Overrides the label read by screen readers. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

### BillingToggle

`import { BillingToggle } from "@/components/goodui-native/segmented-control/segmented-control";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` (required) | `"monthly" \| "yearly"` | – | The selected period. |
| `onValueChange` (required) | `(value: BillingPeriod) => void` | – | Called with the new period. |
| `savings` | `string` | – | Badge on the yearly option, for example "Save 33%". |
| `labels` | `Partial<BillingToggleLabels>` | – | Overrides for the built-in strings; a GooduiLocaleProvider pack sets them app-wide. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |

## Accessibility

- The track is a tablist and each segment a tab with its selected state. Badges are part of the label.

## Motion

- The highlight's leading edge travels on the snappy spring and its trailing edge on the smooth one, so it stretches and settles.
- Dragging moves the highlight with the finger; release snaps to the nearest segment with velocity.
- Label colors follow how much of the highlight covers them.
- Reduced motion: the highlight moves without stretching.

## Haptics

- select on a tap that changes the value
- select at each segment boundary while dragging

## Performance

- Highlight position and label colors run on the UI thread.

## Notes for AI

- It is controlled: pass value and onValueChange. Values are strings.
- Pair BillingToggle with rolling-number for the price.
- Give it an accessibilityLabel that names what it switches.

## Related

- [Rolling number](https://goodui.dev/native/components/rolling-number.md): A number whose digits roll in the direction of change, with digits that open and close in place and currency signs that glide instead of jumping.

## Guidance for AI tools

Segmented control: Two to five views of the same thing with an elastic highlight that stretches toward the new segment, can be dragged, and ticks at every boundary. Includes a billing toggle. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
