

<Preview name="ToggleGroupSegmentedExample" />

## Overview [#overview]

The `ToggleGroup` component manages related toggle buttons. Use the default variant for lightweight ghost-button groups, the outline variant for bordered groups, and the segmented variant for single-selection controls with an animated thumb.

## Usage [#usage]

```tsx
import {
  ToggleGroup,
  ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";
```

```tsx
<ToggleGroup defaultValue="center" groupVariant="segmented">
  <ToggleGroupItem value="left">Left</ToggleGroupItem>
  <ToggleGroupItem value="center">Center</ToggleGroupItem>
  <ToggleGroupItem value="right">Right</ToggleGroupItem>
</ToggleGroup>
```

<Accordions type="single">
  <Accordion title="URL State">
    Sync selection with the URL by providing a `paramName`. Single-select groups use a string value, while multi-select groups use a string array.

    ```tsx
    <ToggleGroup
      defaultValue="week"
      groupVariant="segmented"
      paramClearOnDefault
      paramName="view"
    >
      <ToggleGroupItem value="day">Day</ToggleGroupItem>
      <ToggleGroupItem value="week">Week</ToggleGroupItem>
      <ToggleGroupItem value="month">Month</ToggleGroupItem>
    </ToggleGroup>
    ```
  </Accordion>

  <Accordion title="Polymorphic Items">
    `ToggleGroupItem` supports Base UI's `render` prop. Set `nativeButton={false}` when rendering a non-button element such as a link.

    ```tsx
    <ToggleGroup defaultValue="week" groupVariant="segmented">
      <ToggleGroupItem value="day">Day</ToggleGroupItem>
      <ToggleGroupItem
        nativeButton={false}
        render={<a href="#week" />}
        value="week"
      >
        Week
      </ToggleGroupItem>
    </ToggleGroup>
    ```
  </Accordion>
</Accordions>

## Examples [#examples]

### Segmented [#segmented]

Single-selection segmented groups use the same track, thumb, separator, and hover model as `Tabs`.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupSegmentedExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";
    import {
      TextAlignCenter,
      TextAlignLeft,
      TextAlignRight,
    } from "@tilt-legal/cubitt-icons/ui/outline";

    export default function Example() {
      return (
        <ToggleGroup defaultValue="center" groupVariant="segmented" size="lg">
          <ToggleGroupItem aria-label="Align left" mode="icon" value="left">
            <TextAlignLeft />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Align center" mode="icon" value="center">
            <TextAlignCenter />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Align right" mode="icon" value="right">
            <TextAlignRight />
          </ToggleGroupItem>
        </ToggleGroup>
      );
    }
    ```
  </Tab>
</Tabs>

### Default [#default]

Default groups behave like related ghost toggles and support multiple active items.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="BasicToggleGroupExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";
    import {
      TextBold,
      TextItalic,
      TextUnderline,
    } from "@tilt-legal/cubitt-icons/ui/outline";

    export default function Example() {
      return (
        <ToggleGroup defaultValue={["bold"]} size="lg">
          <ToggleGroupItem aria-label="Toggle bold" value="bold">
            <TextBold />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Toggle italic" value="italic">
            <TextItalic />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Toggle underline" value="underline">
            <TextUnderline />
          </ToggleGroupItem>
        </ToggleGroup>
      );
    }
    ```
  </Tab>
</Tabs>

### Outline [#outline]

Outline groups add a contextual border around related toggle items.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupOutlineExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";
    import {
      TextBold,
      TextItalic,
      TextUnderline,
    } from "@tilt-legal/cubitt-icons/ui/outline";

    export default function Example() {
      return (
        <ToggleGroup
          defaultValue={["bold", "italic"]}
          groupVariant="outline"
          size="lg"
        >
          <ToggleGroupItem aria-label="Toggle bold" value="bold">
            <TextBold />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Toggle italic" value="italic">
            <TextItalic />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="Toggle underline" value="underline">
            <TextUnderline />
          </ToggleGroupItem>
        </ToggleGroup>
      );
    }
    ```
  </Tab>
</Tabs>

### Sizes [#sizes]

Segmented groups support text and icon-only layouts at each size.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupSegmentedSizesExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <div className="flex flex-col items-start gap-10">
      <ToggleGroup defaultValue="week" groupVariant="segmented" size="sm">
        <ToggleGroupItem value="day">Day</ToggleGroupItem>
        <ToggleGroupItem value="week">Week</ToggleGroupItem>
        <ToggleGroupItem value="month">Month</ToggleGroupItem>
        <ToggleGroupItem value="year">Year</ToggleGroupItem>
      </ToggleGroup>

      <ToggleGroup defaultValue="week" groupVariant="segmented" size="md">
        <ToggleGroupItem value="day">Day</ToggleGroupItem>
        <ToggleGroupItem value="week">Week</ToggleGroupItem>
        <ToggleGroupItem value="month">Month</ToggleGroupItem>
        <ToggleGroupItem value="year">Year</ToggleGroupItem>
      </ToggleGroup>

      <ToggleGroup defaultValue="week" groupVariant="segmented" size="lg">
        <ToggleGroupItem value="day">Day</ToggleGroupItem>
        <ToggleGroupItem value="week">Week</ToggleGroupItem>
        <ToggleGroupItem value="month">Month</ToggleGroupItem>
        <ToggleGroupItem value="year">Year</ToggleGroupItem>
      </ToggleGroup>
    </div>
    ```
  </Tab>
</Tabs>

### Separator [#separator]

Use `ToggleGroupSeparator` inside segmented groups to split related options. Separators hide when the active thumb touches them.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupSegmentedSeparatorExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      ToggleGroup,
      ToggleGroupItem,
      ToggleGroupSeparator,
    } from "@tilt-legal/cubitt-components/toggle-group";

    export default function Example() {
      return (
        <ToggleGroup defaultValue="day" groupVariant="segmented" size="lg">
          <ToggleGroupItem value="day">Day</ToggleGroupItem>
          <ToggleGroupItem value="week">Week</ToggleGroupItem>
          <ToggleGroupSeparator />
          <ToggleGroupItem value="month">Month</ToggleGroupItem>
          <ToggleGroupItem value="year">Year</ToggleGroupItem>
        </ToggleGroup>
      );
    }
    ```
  </Tab>
</Tabs>

### URL State [#url-state]

Sync toggle group selection with the URL.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupUrlStateExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <ToggleGroup defaultValue="week" groupVariant="segmented" paramName="view">
      <ToggleGroupItem value="day">Day</ToggleGroupItem>
      <ToggleGroupItem value="week">Week</ToggleGroupItem>
      <ToggleGroupItem value="month">Month</ToggleGroupItem>
      <ToggleGroupItem value="year">Year</ToggleGroupItem>
    </ToggleGroup>
    ```
  </Tab>
</Tabs>

### Polymorphic [#polymorphic]

Render items through custom elements while preserving pressed state.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ToggleGroupSegmentedPolymorphicExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";

    export default function Example() {
      return (
        <ToggleGroup defaultValue="week" groupVariant="segmented" size="lg">
          <ToggleGroupItem value="day">Day</ToggleGroupItem>
          <ToggleGroupItem
            nativeButton={false}
            render={<a href="#week" />}
            value="week"
          >
            Week
          </ToggleGroupItem>
          <ToggleGroupItem
            nativeButton={false}
            render={<a href="#month" />}
            value="month"
          >
            Month
          </ToggleGroupItem>
          <ToggleGroupItem value="year">Year</ToggleGroupItem>
        </ToggleGroup>
      );
    }
    ```
  </Tab>
</Tabs>

## API Reference [#api-reference]

### ToggleGroup [#togglegroup]

The root container that manages toggle selection.

| Prop            | Type                                    | Default        | Description                                                               |
| --------------- | --------------------------------------- | -------------- | ------------------------------------------------------------------------- |
| `value`         | `string \| string[]`                    | -              | Controlled selected value or values.                                      |
| `defaultValue`  | `string \| string[]`                    | -              | Initial selected value or values for uncontrolled usage.                  |
| `onValueChange` | `(value: string \| string[]) => void`   | -              | Called when selection changes.                                            |
| `multiple`      | `boolean`                               | auto           | Enables multiple selection. Segmented groups always use single selection. |
| `groupVariant`  | `"default" \| "outline" \| "segmented"` | `"default"`    | Visual group style.                                                       |
| `variant`       | `"default" \| "outline"`                | `"default"`    | Toggle item variant for non-segmented groups.                             |
| `size`          | `"sm" \| "md" \| "lg"`                  | `"md"`         | Toggle item size.                                                         |
| `disabled`      | `boolean`                               | `false`        | Disables the whole group.                                                 |
| `loop`          | `boolean`                               | `true`         | Whether keyboard focus loops.                                             |
| `orientation`   | `"horizontal" \| "vertical"`            | `"horizontal"` | Group orientation.                                                        |
| `className`     | `string`                                | -              | Additional classes for layout.                                            |

### URL State Props [#url-state-props]

| Prop                  | Type                                          | Default | Description                                               |
| --------------------- | --------------------------------------------- | ------- | --------------------------------------------------------- |
| `paramName`           | `string`                                      | -       | Search parameter name used for URL state.                 |
| `onUrlValueChange`    | `(value: string \| string[] \| null) => void` | -       | Called when the URL-backed value changes.                 |
| `paramClearOnDefault` | `boolean`                                     | `true`  | Removes the URL parameter when value matches the default. |
| `paramThrottle`       | `number`                                      | -       | Throttles URL updates in milliseconds.                    |
| `paramDebounce`       | `number`                                      | -       | Debounces URL updates in milliseconds.                    |

### ToggleGroupItem [#togglegroupitem]

| Prop           | Type                       | Default   | Description                                                    |
| -------------- | -------------------------- | --------- | -------------------------------------------------------------- |
| `value`        | `string`                   | -         | Required unique item value.                                    |
| `mode`         | `"icon"`                   | -         | Square icon-only sizing. Segmented icon items render circular. |
| `disabled`     | `boolean`                  | `false`   | Disables one item.                                             |
| `variant`      | `"default" \| "outline"`   | inherited | Overrides the item variant for non-segmented groups.           |
| `size`         | `"sm" \| "md" \| "lg"`     | inherited | Overrides the item size.                                       |
| `render`       | `ReactElement \| function` | -         | Renders as a custom element or component.                      |
| `nativeButton` | `boolean`                  | `true`    | Set to `false` when `render` outputs a non-button element.     |
| `className`    | `string`                   | -         | Additional item classes.                                       |
| `children`     | `React.ReactNode`          | -         | Item content.                                                  |

### ToggleGroupSeparator [#togglegroupseparator]

| Prop        | Type     | Default | Description                   |
| ----------- | -------- | ------- | ----------------------------- |
| `className` | `string` | -       | Additional separator classes. |

### Notes [#notes]

* Use `multiple` for multi-select default or outline groups.
* Segmented groups force single selection so the animated thumb always has one target.
* Use `aria-label` for icon-only items.
* The segmented variant respects `prefers-reduced-motion`.
