---
title: "ToggleGroup"
description: "A set of buttons that can be pressed on or off."
canonical_url: "https://ui.nuxt.com/docs/components/toggle-group"
---
# ToggleGroup

> A set of buttons that can be pressed on or off.

## Usage

Use the `v-model` directive to control the pressed items of the ToggleGroup.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    value: "left",
    icon: "i-lucide-align-left",
    "aria-label": "Align left"
  },
  {
    value: "center",
    icon: "i-lucide-align-center",
    "aria-label": "Align center"
  },
  {
    value: "right",
    icon: "i-lucide-align-right",
    "aria-label": "Align right"
  }
])
const value = ref("left")
</script>

<template>
  <UToggleGroup v-model="value" :items="items" />
</template>
```

Use the `default-value` prop to set the initial value when you do not need to control its state.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    value: "left",
    icon: "i-lucide-align-left",
    "aria-label": "Align left"
  },
  {
    value: "center",
    icon: "i-lucide-align-center",
    "aria-label": "Align center"
  },
  {
    value: "right",
    icon: "i-lucide-align-right",
    "aria-label": "Align right"
  }
])
</script>

<template>
  <UToggleGroup default-value="left" :items="items" />
</template>
```

### Items

Use the `items` prop as an array of objects that accept the [Button](https://ui.nuxt.com/docs/components/button) props except the link ones, plus a `value` that defaults to the index as a string, so the model holds strings too:

- `value?: AcceptableValue`{lang="ts-type"}
- `label?: string`{lang="ts-type"}
- `icon?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: ButtonProps['ui']`{lang="ts-type"}

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup default-value="week" :items="items" />
</template>
```

### Multiple

Set the `type` prop to `multiple` to allow several items to be pressed at once. The model value is then an array.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    value: "bold",
    icon: "i-lucide-bold",
    "aria-label": "Toggle bold"
  },
  {
    value: "italic",
    icon: "i-lucide-italic",
    "aria-label": "Toggle italic"
  },
  {
    value: "underline",
    icon: "i-lucide-underline",
    "aria-label": "Toggle underline"
  }
])
</script>

<template>
  <UToggleGroup type="multiple" :default-value="[
  'bold',
  'italic'
]" :items="items" />
</template>
```

### Orientation

Use the `orientation` prop to change the orientation of the ToggleGroup. Defaults to `horizontal`.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup orientation="vertical" default-value="week" :items="items" />
</template>
```

### Attached

Use the `attached` prop to attach the items together, like in a [FieldGroup](https://ui.nuxt.com/docs/components/field-group).

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup attached variant="outline" active-variant="subtle" default-value="week" :items="items" />
</template>
```

### Color

Use the `color` and `active-color` props to set the color of the items when not pressed and when pressed. Defaults to `neutral` and `primary`.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup color="neutral" active-color="neutral" default-value="week" :items="items" />
</template>
```

### Variant

Use the `variant` and `active-variant` props to set the variant of the items when not pressed and when pressed. Defaults to `ghost` and `soft`.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup variant="outline" active-variant="subtle" default-value="week" :items="items" />
</template>
```

### Size

Use the `size` prop to set the size of the items.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup size="xl" default-value="week" :items="items" />
</template>
```

### Disabled

Use the `disabled` prop to disable the ToggleGroup.

```vue
<script setup lang="ts">
import type { ToggleGroupItem } from '@nuxt/ui'

const items = ref<ToggleGroupItem[]>([
  {
    label: "Day",
    value: "day"
  },
  {
    label: "Week",
    value: "week"
  },
  {
    label: "Month",
    value: "month"
  }
])
</script>

<template>
  <UToggleGroup disabled default-value="week" :items="items" />
</template>
```

## API

### Props

```ts
/**
 * Props for the ToggleGroup component
 */
interface ToggleGroupProps {
  /**
   * The element or component this component should render as.
   * @default 'div'
   */
  as?: any;
  items?: T[] | undefined;
  /**
   * The color of the items.
   * @default 'neutral'
   */
  color?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
  /**
   * The variant of the items.
   * @default 'ghost'
   */
  variant?: "solid" | "outline" | "soft" | "subtle" | "ghost" | "link" | undefined;
  /**
   * The color of the pressed items.
   * @default 'primary'
   */
  activeColor?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | undefined;
  /**
   * The variant of the pressed items.
   * @default 'soft'
   */
  activeVariant?: "solid" | "outline" | "soft" | "subtle" | "ghost" | "link" | undefined;
  size?: "xs" | "sm" | "md" | "lg" | "xl" | undefined;
  /**
   * The orientation the items are laid out.
   * @default 'horizontal'
   */
  orientation?: "horizontal" | "vertical" | undefined;
  /**
   * Attach the items together, like in a FieldGroup.
   */
  attached?: boolean | undefined;
  /**
   * The key used to get the value from the item.
   * @default 'value'
   */
  valueKey?: keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>> | undefined;
  /**
   * The key used to get the label from the item.
   * @default 'label'
   */
  labelKey?: keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>> | undefined;
  ui?: { root?: SlotClass; item?: SlotClass; } | undefined;
  /**
   * Determines whether a "single" or "multiple" items can be selected at a time.
   * 
   * This prop will overwrite the inferred type from `modelValue` and `defaultValue`.
   * @default 'single'
   */
  type?: "single" | "multiple" | undefined;
  /**
   * The controlled value of the active item(s).
   * 
   * Use this when you need to control the state of the items. Can be binded with `v-model`
   */
  modelValue?: null | string | number | bigint | Record<string, any> | AcceptableValue[] | undefined;
  /**
   * The default active value of the item(s).
   * 
   * Use when you do not need to control the state of the item(s).
   */
  defaultValue?: null | string | number | bigint | Record<string, any> | AcceptableValue[] | undefined;
  /**
   * When `true`, prevents the user from interacting with the toggle group and all its items.
   */
  disabled?: boolean | undefined;
  /**
   * When `loop` and `rovingFocus` is `true`, keyboard navigation will loop from last item to first, and vice versa.
   * @default true
   */
  loop?: boolean | undefined;
  /**
   * When `false`, navigating through the items using arrow keys will be disabled.
   * @default true
   */
  rovingFocus?: boolean | undefined;
  /**
   * The name of the field. Submitted with its owning form as part of a name/value pair.
   */
  name?: string | undefined;
  /**
   * When `true`, indicates that the user must set the value before the owning form can be submitted.
   */
  required?: boolean | undefined;
}
```

### Slots

```ts
/**
 * Slots for the ToggleGroup component
 */
interface ToggleGroupSlots {
  leading(): any;
  default(): any;
  trailing(): any;
}
```

### Emits

```ts
/**
 * Emitted events for the ToggleGroup component
 */
interface ToggleGroupEmits {
  change: (payload: [event: Event]) => void;
  update:modelValue: (payload: [payload: AcceptableValue | AcceptableValue[]]) => void;
}
```

## Theme

```ts [app.config.ts]
export default defineAppConfig({
  ui: {
    toggleGroup: {
      slots: {
        root: 'relative',
        item: ''
      },
      variants: {
        orientation: {
          horizontal: {
            root: 'inline-flex items-center gap-1'
          },
          vertical: {
            root: 'flex flex-col gap-1'
          }
        },
        fieldGroup: {
          horizontal: {
            root: 'gap-0 -space-x-px',
            item: 'first:not-nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-e-none not-first:nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-s-none not-first:not-nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-none focus-visible:z-[1] data-[state=on]:z-[1] focus-visible:z-[2]'
          },
          vertical: {
            root: 'gap-0 -space-y-px',
            item: 'first:not-nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-b-none not-first:nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-t-none not-first:not-nth-last-[1_of_:not(input[aria-hidden],select[aria-hidden])]:rounded-none focus-visible:z-[1] data-[state=on]:z-[1] focus-visible:z-[2]'
          }
        }
      }
    }
  }
})
```

## Changelog

See commit history for [component](https://github.com/nuxt/ui/commits/v4/src/runtime/components/ToggleGroup.vue) and [theme](https://github.com/nuxt/ui/commits/v4/src/theme/toggle-group.ts).

---

- [ToggleGroup](https://reka-ui.com/docs/components/toggle-group)
- [GitHub](https://github.com/nuxt/ui/blob/v4/src/runtime/components/ToggleGroup.vue)


## Sitemap

See the full [sitemap](https://ui.nuxt.com/sitemap.md) for all pages.
