# SegmentedControl
A horizontal control composed of mutually exclusive segments, used to switch between related options.
## Import
```tsx
import { SegmentedControl } from '@coinbase/cds-web/controls/SegmentedControl'
```
## Examples
SegmentedControl uses native radio inputs with labels to provide an accessible, compact switch between options. It supports both text labels and icon options.
### Basics
Pass an array of `options` with `value` and `label` properties. Use `value` and `onChange` for controlled usage, or omit them for uncontrolled behavior. The component manages its own state when uncontrolled.
```jsx live
function SegmentedControlBasic() {
const options = [
{ value: 'eth', label: 'ETH' },
{ value: 'usd', label: 'USD' },
{ value: 'btc', label: 'BTC' },
];
const [selected, setSelected] = useState('eth');
return (
Selected: {selected}
);
}
```
#### Uncontrolled
When you omit `value` and `onChange`, SegmentedControl manages selection internally. Use `onChange` only when you need to react to changes.
```jsx live
function SegmentedControlUncontrolled() {
const options = [
{ value: 'list', label: 'List' },
{ value: 'grid', label: 'Grid' },
];
return ;
}
```
### Icons
For icon-only segments, set `type="icon"` and provide `iconSize` and options with `label` as an icon name. Use `accessibilityLabel` on each option for screen readers.
```jsx live
function SegmentedControlIcons() {
const options = [
{ value: 'eth', label: 'ethereum', accessibilityLabel: 'Ethereum' },
{ value: 'usd', label: 'cashUSD', accessibilityLabel: 'US Dollar' },
];
const [value, setValue] = useState('eth');
return (
);
}
```
You can also set `active` to `true` to apply an active icon style.
```jsx live
function SegmentedControlActiveIcons() {
const options = [
{ value: 'eth', label: 'ethereum', accessibilityLabel: 'Ethereum', active: true },
{ value: 'usd', label: 'cashUSD', accessibilityLabel: 'US Dollar' },
];
const [value, setValue] = useState('eth');
return (
);
}
```
### Disabled
Disable the entire control with the `disabled` prop.
```jsx live
function SegmentedControlDisabled() {
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
];
return ;
}
```
### Accessibility
Provide `accessibilityLabel` on each option when using icons so screen readers can announce the segment. For text options, the label text is used automatically.
```jsx live
function SegmentedControlAccessible() {
const options = [
{ value: 'eth', label: 'ethereum', accessibilityLabel: 'View in Ethereum' },
{ value: 'usd', label: 'cashUSD', accessibilityLabel: 'View in US Dollars' },
];
const [value, setValue] = useState('eth');
return (
);
}
```
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `iconSize` | `xs \| s \| m \| l` | Yes | `-` | - |
| `options` | `TextOptions \| IconOptions` | Yes | `-` | The options to render as an array of values and labels The options to render as an array of values and IconNames |
| `block` | `boolean` | No | `-` | Expand to 100% of parent width |
| `disabled` | `boolean` | No | `-` | - |
| `key` | `Key \| null` | No | `-` | - |
| `onChange` | `((value: string) => void)` | No | `-` | Callback fired when an option is selected |
| `ref` | `((instance: HTMLInputElement \| null) => void) \| RefObject \| null` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `type` | `text \| icon` | No | `-` | - |
| `value` | `string` | No | `-` | The selected value |