---
title: Toggle Group
description: A set of two-state buttons that can be toggled on or off.
icon: ellipsis
author:
  name: imskyleen
  url: https://github.com/imskyleen
related:
  - /toggle
  - /tabs
mode: wide
---

<PoweredBy
  packages={[
    { name: 'Base UI', url: 'https://base-ui.com/react/components/toggle-group' },
    { name: 'Shadcn UI', url: 'https://ui.shadcn.com/docs/components/toggle-group' },
    { name: 'Animate UI', url: 'https://animate-ui.com/docs/base/toggle-group' },
  ]}
/>

### Installation

```package-install
npx shadcn@latest add @redpanda/toggle-group
```

<ComponentPreview name="toggle-group-demo" />

## When to use

Toggle Group operates as a segmented control, allowing users to filter or adjust the display of content within the current view. Unlike tabs that navigate between distinct content areas, segmented controls modify how existing content is presented. Content is typically shared across different segments, with the control determining what's visible or how it's formatted.

**Use Toggle Group when:**

- Filtering or adjusting a single content view
- Toggling between different presentations of the same data
- Content is shared across segments (list vs. grid, day vs. week vs. month)
- Making formatting choices (bold, italic, underline)
- The view context remains the same, just filtered or adjusted

**Don't use Toggle Group when:**

- Navigating between completely different content areas (use Tabs instead)
- Each option shows unique, non-overlapping content
- The interaction triggers a full content change rather than a filter/adjustment

```mermaid
graph TD;
    START[What's the interaction?] --> INTENT{What changes?};

    INTENT -->|Filters/adjusts current view| SEG[✅ Use Toggle Group<br/>Segmented Control];
    INTENT -->|Navigates to new content| TABS[⚠️ Use Tabs instead];

    SEG --> TYPE{Selection behavior?};
    TYPE -->|Single selection| SINGLE[✅ omit multiple<br/>single-select behavior];
    TYPE -->|Multiple selection| MULTI[✅ multiple<br/>independent toggles];

    SINGLE --> VARIANT{Visual style?};
    MULTI --> VARIANT;

    VARIANT -->|Contained group| DEFAULT[✅ default variant<br/>Attached items];
    VARIANT -->|Outlined container| OUTLINE[✅ outline variant<br/>Border around group];

    TABS --> TABINFO[Tabs navigate between<br/>distinct content areas];

    classDef recommended fill:#4ade80,stroke:#22c55e,stroke-width:2px,color:#000;
    classDef discouraged fill:#fbbf24,stroke:#f59e0b,stroke-width:2px,color:#000;
    classDef decision fill:#60a5fa,stroke:#3b82f6,stroke-width:2px,color:#fff;
    classDef info fill:#8b5cf6,stroke:#7c3aed,stroke-width:2px,color:#fff;

    class SEG,SINGLE,MULTI,DEFAULT,OUTLINE recommended;
    class TABS discouraged;
    class START,INTENT,TYPE,VARIANT decision;
    class TABINFO info;
```

## Usage

```tsx
<ToggleGroup>
  <ToggleGroupItem value="a">A</ToggleGroupItem>
  <ToggleGroupItem value="b">B</ToggleGroupItem>
  <ToggleGroupItem value="c">C</ToggleGroupItem>
</ToggleGroup>
```

Choices may come from fragments or a shared component, as the attached-mode example demonstrates.
Keep their rendered buttons as direct DOM siblings of the group; attachment follows the actual first
and last button, not the shape of the React children. An attached group with one choice rounds every corner.

## Interaction states

A segment is transparent at rest, so it takes the two archetypes from
[Interaction states](/docs/interaction-states) according to whether it is the chosen one:

|                | rest            | hover            | held               |
| -------------- | --------------- | ---------------- | ------------------ |
| **Unselected** | transparent     | `accent` wash    | `accent-pressed`   |
| **Selected**   | `selected` fill | `selected-hover` | `selected-pressed` |

The hover is scoped to unselected segments, so the chosen one steps its own fill instead of taking a wash on
top of it. Selection looks the same whether the group is single-select or `multiple`, and the transition is
colour only — nothing moves, and it is dropped under `prefers-reduced-motion`.

## Examples

### Multiple

<ComponentPreview name="toggle-group-multiple-demo" />

### Outline Variant

The outline variant provides a bordered container around the toggle group, ideal for segmented controls that filter or adjust content.

<ComponentPreview
  name="toggle-group-outline-demo"
  description="Toggle group with outline variant for view mode selection"
/>

### Attached Mode

<ComponentPreview
  name="toggle-group-attached-demo"
  description="Toggle group demonstrating attached and detached modes with proper border-radius handling"
/>

### Vertical Orientation

<ComponentPreview
  name="toggle-group-vertical-demo"
  description="Toggle group rendered vertically for view-mode pickers in narrow sidebars."
/>

### Shifting Layout

Each segment paints its own selection, so a group whose surrounding layout resizes between selections has
nothing to re-measure and nothing to chase — the selected segment is simply where it was.

<ComponentPreview
  name="toggle-group-shifting-layout-demo"
  description="Toggle group whose page position changes between selections."
/>

### Combined with Tabs

This example demonstrates the key difference between tabs (navigation) and toggle groups (filtering). Tabs navigate between different content areas, while toggle groups filter or adjust content within each tab's view.

<ComponentPreview
  name="tabs-with-toggle-group-demo"
  description="Real-world example showing tabs for navigation and toggle groups for filtering within each tab"
/>

## Props

<div className="flex flex-row gap-x-3">
  <ExternalLink href="https://base-ui.com/react/components/toggle-group" text="Docs" />
  <ExternalLink href="https://base-ui.com/react/components/toggle-group#api-reference" text="API Reference" />
</div>

### Registry Props

#### ToggleGroup

| Prop | Type | Default | Description |
| - | - | - | - |
| `multiple?` | `boolean` | `false` | Allow multiple items to be pressed at once. Omit for single-select. `value`/`defaultValue` are always arrays. |
| `attached?` | `boolean` | `true` | Join the segments into one control, squaring the inner corners. Set `false` for separately rounded segments with a gap. |
| `orientation?` | `'horizontal' \| 'vertical'` | `horizontal` | Lay the segments out in a row or a column. |
| `variant?` | `'default' \| 'outline'` | `default` | The variant of the toggle group |
| `size?` | `'sm' \| 'md' \| 'lg'` | `md` | The size of the toggle group |

#### ToggleGroupItem

| Prop | Type | Default | Description |
| - | - | - | - |
| `children` | `React.ReactNode` | - | The children of the toggle group item |
| `variant?` | `'default' \| 'outline'` | `default` | The variant of the toggle group item |
| `size?` | `'sm' \| 'md' \| 'lg'` | `md` | The size of the toggle group item |

## Keyboard interactions

| Key                        | Action                                                                |
| -------------------------- | --------------------------------------------------------------------- |
| `Tab` into the group       | Focus lands on the currently-pressed item, or the first item if none. |
| `ArrowLeft` / `ArrowRight` | Moves between items (horizontal).                                     |
| `ArrowUp` / `ArrowDown`    | Moves between items (vertical).                                       |
| `Space` / `Enter`          | Toggles the focused item.                                             |
| `Home` / `End`             | Jumps to first / last item.                                           |

## Accessibility

- The container carries `role="group"` and each item is an `aria-pressed` toggle button (Base UI native
  semantics).
- Focus is roving — only one item is tabbable at a time, and arrow keys move focus between items.
- Provide an accessible group label — either `aria-label` on `ToggleGroup` or a visible heading with
  `aria-labelledby` — otherwise the purpose of the group isn't announced.
- Omit `multiple` for single-selection filters (like/dislike, sort direction) and pass `multiple` for
  independent switches (text formatting, feature flags). `value`/`defaultValue` are always arrays.

## Credits

- We use [Base UI](https://base-ui.com/react/components/toggle-group) for the toggle group component.
- We take our inspiration from [Shadcn UI](https://ui.shadcn.com/docs/components/toggle-group) for the toggle group style.
