---
type: doc
title: Toggle Group
description: A set of two-state buttons that can be toggled independently or as a single choice.
---

> Fulldev UI for Astro. The `@fulldev` registry in `components.json` points at `https://ui.full.dev/r/styles/{style}/{name}.json`; see [installation](/astro/docs/installation.md).

```astro title="src/components/examples/toggle-group/toggle-group-demo.astro"
---
import Bold from "@lucide/astro/icons/bold"
import Italic from "@lucide/astro/icons/italic"
import Underline from "@lucide/astro/icons/underline"

import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<ToggleGroup variant="outline" multiple>
  <ToggleGroupItem value="bold" aria-label="Toggle bold">
    <Bold />
  </ToggleGroupItem>
  <ToggleGroupItem value="italic" aria-label="Toggle italic">
    <Italic />
  </ToggleGroupItem>
  <ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
    <Underline />
  </ToggleGroupItem>
</ToggleGroup>
```

## Installation

```bash
npx shadcn@latest add @fulldev/toggle-group
```

## Usage

```ts
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
```

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

## Composition

```text
ToggleGroup
├── ToggleGroupItem
└── ToggleGroupItem
```

## Outline

Use `variant="outline"` for an outline style.

```astro title="src/components/examples/toggle-group/toggle-group-outline.astro"
---
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<ToggleGroup variant="outline" defaultValue={["all"]}>
  <ToggleGroupItem value="all" aria-label="Toggle all">
    All
  </ToggleGroupItem>
  <ToggleGroupItem value="missed" aria-label="Toggle missed">
    Missed
  </ToggleGroupItem>
</ToggleGroup>
```

## Size

Use the `size` prop to change the size of the toggle group.

```astro title="src/components/examples/toggle-group/toggle-group-sizes.astro"
---
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<div class="flex flex-col gap-4">
  <ToggleGroup size="sm" defaultValue={["top"]} variant="outline">
    <ToggleGroupItem value="top" aria-label="Toggle top">
      Top
    </ToggleGroupItem>
    <ToggleGroupItem value="bottom" aria-label="Toggle bottom">
      Bottom
    </ToggleGroupItem>
    <ToggleGroupItem value="left" aria-label="Toggle left">
      Left
    </ToggleGroupItem>
    <ToggleGroupItem value="right" aria-label="Toggle right">
      Right
    </ToggleGroupItem>
  </ToggleGroup>
  <ToggleGroup defaultValue={["top"]} variant="outline">
    <ToggleGroupItem value="top" aria-label="Toggle top">
      Top
    </ToggleGroupItem>
    <ToggleGroupItem value="bottom" aria-label="Toggle bottom">
      Bottom
    </ToggleGroupItem>
    <ToggleGroupItem value="left" aria-label="Toggle left">
      Left
    </ToggleGroupItem>
    <ToggleGroupItem value="right" aria-label="Toggle right">
      Right
    </ToggleGroupItem>
  </ToggleGroup>
</div>
```

## Spacing

Use `spacing` to set the gap between items. The default is `2`; use
`spacing={0}` for connected items.

```astro title="src/components/examples/toggle-group/toggle-group-spacing.astro"
---
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<ToggleGroup size="sm" defaultValue={["top"]} variant="outline" spacing={2}>
  <ToggleGroupItem value="top" aria-label="Toggle top">
    Top
  </ToggleGroupItem>
  <ToggleGroupItem value="bottom" aria-label="Toggle bottom">
    Bottom
  </ToggleGroupItem>
  <ToggleGroupItem value="left" aria-label="Toggle left">
    Left
  </ToggleGroupItem>
  <ToggleGroupItem value="right" aria-label="Toggle right">
    Right
  </ToggleGroupItem>
</ToggleGroup>
```

## Vertical

Use `orientation="vertical"` for vertical toggle groups. Arrow keys follow the
orientation.

```astro title="src/components/examples/toggle-group/toggle-group-vertical.astro"
---
import BoldIcon from "@lucide/astro/icons/bold"
import ItalicIcon from "@lucide/astro/icons/italic"
import UnderlineIcon from "@lucide/astro/icons/underline"

import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<ToggleGroup
  multiple
  orientation="vertical"
  spacing={1}
  defaultValue={["bold", "italic"]}
>
  <ToggleGroupItem value="bold" aria-label="Toggle bold">
    <BoldIcon />
  </ToggleGroupItem>
  <ToggleGroupItem value="italic" aria-label="Toggle italic">
    <ItalicIcon />
  </ToggleGroupItem>
  <ToggleGroupItem value="underline" aria-label="Toggle underline">
    <UnderlineIcon />
  </ToggleGroupItem>
</ToggleGroup>
```

## Disabled

```astro title="src/components/examples/toggle-group/toggle-group-disabled.astro"
---
import Bold from "@lucide/astro/icons/bold"
import Italic from "@lucide/astro/icons/italic"
import Underline from "@lucide/astro/icons/underline"

import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
---

<ToggleGroup disabled>
  <ToggleGroupItem value="bold" aria-label="Toggle bold">
    <Bold />
  </ToggleGroupItem>
  <ToggleGroupItem value="italic" aria-label="Toggle italic">
    <Italic />
  </ToggleGroupItem>
  <ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
    <Underline />
  </ToggleGroupItem>
</ToggleGroup>
```

## Custom

A custom toggle group that shows the selected value through the
`toggle-group:change` event.

```astro title="src/components/examples/toggle-group/toggle-group-font-weight-selector.astro"
---
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

const fontWeight = "normal"
---

<Field data-font-weight-selector>
  <FieldLabel>Font Weight</FieldLabel>
  <ToggleGroup
    defaultValue={[fontWeight]}
    variant="outline"
    spacing={2}
    size="lg"
  >
    <ToggleGroupItem
      value="light"
      aria-label="Light"
      class="flex size-16 flex-col items-center justify-center rounded-xl"
    >
      <span class="text-2xl leading-none font-light">Aa</span>
      <span class="text-xs text-muted-foreground">Light</span>
    </ToggleGroupItem>
    <ToggleGroupItem
      value="normal"
      aria-label="Normal"
      class="flex size-16 flex-col items-center justify-center rounded-xl"
    >
      <span class="text-2xl leading-none font-normal">Aa</span>
      <span class="text-xs text-muted-foreground">Normal</span>
    </ToggleGroupItem>
    <ToggleGroupItem
      value="medium"
      aria-label="Medium"
      class="flex size-16 flex-col items-center justify-center rounded-xl"
    >
      <span class="text-2xl leading-none font-medium">Aa</span>
      <span class="text-xs text-muted-foreground">Medium</span>
    </ToggleGroupItem>
    <ToggleGroupItem
      value="bold"
      aria-label="Bold"
      class="flex size-16 flex-col items-center justify-center rounded-xl"
    >
      <span class="text-2xl leading-none font-bold">Aa</span>
      <span class="text-xs text-muted-foreground">Bold</span>
    </ToggleGroupItem>
  </ToggleGroup>
  <FieldDescription>
    Use{" "}
    <code
      class="rounded-md bg-muted px-1 py-0.5 font-mono"
      data-font-weight-class
    >
      font-{fontWeight}
    </code>{" "}
    to set the font weight.
  </FieldDescription>
</Field>

<script>
  const initialize = () => {
    for (const root of document.querySelectorAll(
      "[data-font-weight-selector]"
    )) {
      if (root.hasAttribute("data-bound")) continue
      root.setAttribute("data-bound", "")
      const output = root.querySelector("[data-font-weight-class]")
      root
        .querySelector('[data-slot="toggle-group"]')
        ?.addEventListener("toggle-group:change", (event) => {
          const { value } = (event as CustomEvent<{ value: string[] }>).detail
          if (output) output.textContent = `font-${value[0] ?? ""}`
        })
    }
  }

  initialize()
  document.addEventListener("astro:page-load", initialize)
</script>
```

## RTL

Set `dir="rtl"` on the group or a parent element.

```astro title="src/components/examples/toggle-group/toggle-group-rtl.astro"
---
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

const translations = {
  en: {
    dir: "ltr",
    values: {
      list: "List",
      grid: "Grid",
      cards: "Cards",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      list: "قائمة",
      grid: "شبكة",
      cards: "بطاقات",
    },
  },
  he: {
    dir: "rtl",
    values: {
      list: "רשימה",
      grid: "רשת",
      cards: "כרטיסים",
    },
  },
} as const

const { dir, values: t } = translations.ar
---

<ToggleGroup variant="outline" defaultValue={["list"]} dir={dir}>
  <ToggleGroupItem value="list" aria-label={t.list}>
    {t.list}
  </ToggleGroupItem>
  <ToggleGroupItem value="grid" aria-label={t.grid}>
    {t.grid}
  </ToggleGroupItem>
  <ToggleGroupItem value="cards" aria-label={t.cards}>
    {t.cards}
  </ToggleGroupItem>
</ToggleGroup>
```

## API Reference

Source: [`src/components/ui/toggle-group`](https://github.com/fulldotdev/ui/tree/main/src/components/ui/toggle-group)

### ToggleGroup

| Prop           | Type                         | Default        | Description                                  |
| -------------- | ---------------------------- | -------------- | -------------------------------------------- |
| `defaultValue` | `string \| string[]`         | `[]`           | Initial selected value or values.            |
| `multiple`     | `boolean`                    | `false`        | Allows multiple selected items.              |
| `orientation`  | `"horizontal" \| "vertical"` | `"horizontal"` | Sets arrow-key navigation direction.         |
| `loop`         | `boolean`                    | `true`         | Wraps keyboard focus at either end.          |
| `disabled`     | `boolean`                    | `false`        | Blocks interaction for the whole group.      |
| `variant`      | `"default" \| "outline"`     | item default   | Applies a visual variant to every item.      |
| `size`         | `"sm" \| "default" \| "lg"`  | item default   | Applies a size to every item.                |
| `spacing`      | `number`                     | `2`            | Gap between items in Tailwind spacing units. |

### ToggleGroupItem

| Prop       | Type                        | Default     | Description                                   |
| ---------- | --------------------------- | ----------- | --------------------------------------------- |
| `value`    | `string`                    | required    | Unique value for the item.                    |
| `disabled` | `boolean`                   | `false`     | Disables the item.                            |
| `variant`  | `"default" \| "outline"`    | `"default"` | Item variant when the group does not set one. |
| `size`     | `"sm" \| "default" \| "lg"` | `"default"` | Item size when the group does not set one.    |

The root emits `toggle-group:change` with `{ value: string[] }`. Dispatch
`toggle-group:set` with `{ value: string | string[] }` to update it from client
code. See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/toggle-group/README.md)
for controller methods and full keyboard behavior.

## Install what this page shows

```bash
npx shadcn@latest add @fulldev/toggle-group-examples
```
