> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SegmentedControl

> Choose one value from a compact group of labeled or icon options.

export const StoryEmbed = ({storyId, title, height = 240}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`SegmentedControl` is a radio group with joined options. Use it for a short, mutually exclusive choice. For navigation between content panels, use [Tabs](/ui/primitives/navigation/tabs).

<StoryEmbed storyId="ui-input-segmentedcontrol--default" title="SegmentedControl example" />

## Usage

Supply an accessible group name with `aria-label` or `aria-labelledby`. Each option needs a unique string `value`. Selection belongs to the group; options do not have independent checked state.

## Uncontrolled state

```tsx theme={null}
import { SegmentedControl } from 'twenty-ui/primitives/input';

export const BillingPeriod = () => (
  <SegmentedControl
    aria-label="Billing period"
    name="billingPeriod"
    defaultValue="annual"
    options={[
      { label: 'Annual', value: 'annual' },
      { label: 'Monthly', value: 'monthly' },
    ]}
  />
);
```

`defaultValue` initializes selection. The group owns later changes. Add `onValueChange` if you need to observe them without controlling the value.

## Controlled state

```tsx theme={null}
import { useState } from 'react';
import { SegmentedControl } from 'twenty-ui/primitives/input';

export const BillingPeriod = () => {
  const [period, setPeriod] = useState('annual');

  return (
    <SegmentedControl
      aria-label="Billing period"
      name="billingPeriod"
      value={period}
      onValueChange={setPeriod}
      options={[
        { label: 'Annual', value: 'annual' },
        { label: 'Monthly', value: 'monthly' },
      ]}
    />
  );
};
```

Keep `value` in application state and update it in `onValueChange`. Do not combine `value` and `defaultValue` or switch ownership modes after mounting.

## Icon options

```tsx theme={null}
import { SegmentedControl } from 'twenty-ui/primitives/input';
import { IconList, IconLayoutKanban } from 'twenty-ui/icon';

export const RecordLayout = () => (
  <SegmentedControl
    aria-label="Record layout"
    defaultValue="list"
    itemWidth="content"
    options={[
      { value: 'list', startIcon: <IconList />, 'aria-label': 'List' },
      {
        value: 'kanban',
        startIcon: <IconLayoutKanban />,
        'aria-label': 'Kanban',
      },
    ]}
  />
);
```

An icon-only option requires an `aria-label`. `startIcon` is decorative and hidden from assistive technology. Options with visible text use `label` and may also provide `startIcon`. Set `disabled` on an option to prevent its selection, or on the group to disable every option.

## Keyboard, forms, and direction

Tab enters the group; arrow keys move between enabled options and update selection. `itemWidth="equal"` is the default; use `content` when labels should determine widths. Set `name` to include the selected value in native form submission.

For right-to-left content, pair [TextDirectionProvider](/ui/primitives/layout/text-direction-provider) with a matching `dir` attribute. The provider controls directional interaction; `dir` controls the document layout.

## Props

<ParamField body="aria-label" type="string" required>
  Accessible group name. Supply this or `aria-labelledby`.
</ParamField>

<ParamField body="aria-labelledby" type="string" required>
  ID of an element that labels the group. Supply this or `aria-label`.
</ParamField>

<ParamField body="className" type="string | ((state: RadioGroupState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="defaultValue" type="string">
  The uncontrolled value of the radio button that should be initially selected.

  To render a controlled radio group, use the `value` prop instead.
</ParamField>

<ParamField body="disabled" type="boolean" default="false">
  Whether the component should ignore user interaction.
</ParamField>

<ParamField body="form" type="string">
  Identifies the form that owns the radio inputs.
  Useful when the radio group is rendered outside the form.
</ParamField>

<ParamField body="inputRef" type="Ref<HTMLInputElement>">
  A ref to access the hidden input element.
</ParamField>

<ParamField body="itemWidth" type="&#x22;content&#x22; | &#x22;equal&#x22;" default="equal">
  Use equal-width options or size each option to its content.
</ParamField>

<ParamField body="name" type="string">
  Identifies the field when a form is submitted.
</ParamField>

<ParamField body="onValueChange" type="((value: TValue, eventDetails: { reason: &#x22;none&#x22;; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void)">
  Callback fired when the value changes.
</ParamField>

<ParamField body="options" type="readonly SegmentedControlOption<TValue>[]" required>
  Options with a unique string `value`, a `label` or `startIcon`, and optional `disabled`. Icon-only options require an `aria-label`.
</ParamField>

<ParamField body="readOnly" type="boolean" default="false">
  Whether the user should be unable to select a different radio button in the group.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, RadioGroupState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="required" type="boolean" default="false">
  Whether the user must choose a value before submitting a form.
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: RadioGroupState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="value" type="string">
  The controlled value of the radio item that should be currently selected.

  To render an uncontrolled radio group, use the `defaultValue` prop instead.
</ParamField>
