ToggleGroup
Overview
A set of two-state buttons that can be toggled on or off as a group, supporting single and multiple selection. Use it for formatting toolbars, filter chips, or any exclusive (or multi-choice) segmented control where the selection changes immediately. For segmented single options that must look like a unified control, SSegment may fit better; for a single independent on/off button, use SToggle.
Usage
Features
- 🎯 Single / multiple selection —
multipleswitches between one and many selected items, with a type-safe generic value (M extends boolean,T extends DefinedValue) - 🎚 Controlled / uncontrolled —
v-modelanddefaultValue(scalar or array) backed byuseControllableState - ⌨️ Roving focus keyboard navigation — arrow keys move focus between items,
loopwraps around, and arrow direction reverses in RTL - ♿
aria-pressed+data-state(on/off) dual reflection, axe-clean - 🎨 3 variants (outline/soft/ghost) × 6 sizes × 8 colors × 2 orientations via
toggleGroupVariants - 🧩 Per-item full
Buttonprop surface (as/asChild,type, item-leveldisabled), and slot props exposingpressed/disabled - 📝 Form integration —
name/requiredrender a hidden input so the selection submits with the owning form - 🧩
uiper-slot class overrides (root/item)
Component family
SToggleGroup— the group root that manages selection state, orientation, and roving focusSToggleGroupItem— an individual toggleable button; pass a uniquevaluethat identifies it in the group
Demos
Basic
API
Aria Layer
3ToggleGroup<M, T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
color | ThemeColor | — | Theme color of the component. |
size | ThemeSize | — | Visual size of the component. |
variant | ToggleGroupVariant | — | Visual variant of the component. |
ui | Partial<ToggleGroupUi> | — | Per-slot class overrides for the component. |
rovingFocus | boolean | — | When `false`, navigating through items with arrow keys is disabled. |
disabled | boolean | — | When `true`, prevents interaction with all items in the group. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the group when applicable. |
loop | boolean | — | When `true`, keyboard navigation loops from last to first item, and vice versa. |
modelValue | (M extends true ? T[] : T) | — | The controlled value of the selected item(s).
Use this when you need to control the state of the items. Can be bound with `v-model` |
defaultValue | (M extends true ? T[] : T) | — | The default value of the selected item(s).
Use this when you need to set the initial state of the items. |
multiple | M | — | Determines whether a "single" or "multiple" items can be selected at a time.
This prop will overwrite the inferred type from `modelValue` and `defaultValue`. |
clearable | boolean | — | Whether selected item can be cleared when `multiple` is false. |
selectionBehavior | SelectionBehavior | 'toggle' | How multiple selection should behave in the collection. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | M extends true ? T[] : T | — |
ToggleGroupItem<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | — | A unique value that identifies the item inside the group. |
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
ToggleGroupRoot<M, T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
rovingFocus | boolean | — | When `false`, navigating through items with arrow keys is disabled. |
disabled | boolean | — | When `true`, prevents interaction with all items in the group. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the group when applicable. |
loop | boolean | — | When `true`, keyboard navigation loops from last to first item, and vice versa. |
modelValue | (M extends true ? T[] : T) | — | The controlled value of the selected item(s).
Use this when you need to control the state of the items. Can be bound with `v-model` |
defaultValue | (M extends true ? T[] : T) | — | The default value of the selected item(s).
Use this when you need to set the initial state of the items. |
multiple | M | — | Determines whether a "single" or "multiple" items can be selected at a time.
This prop will overwrite the inferred type from `modelValue` and `defaultValue`. |
clearable | boolean | — | Whether selected item can be cleared when `multiple` is false. |
selectionBehavior | SelectionBehavior | 'toggle' | How multiple selection should behave in the collection. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | M extends true ? T[] : T | — |
Notes
Architecture and benchmark differences
VeanUI builds the group from Aria ToggleGroupRoot (useSelection + useRovingFocusGroup + hidden-input form proxy) and ToggleGroupItem (dynamically backed by useRovingFocusGroupItem or the Button base depending on rovingFocus). The UI wrapper SToggleGroup is a thin pass-through that only computes toggleGroupVariants classes; data-state drives the pressed look through UnoCSS data-[state=on]:* selectors. toggle-group is a Radix/shadcn-native pattern; the other benchmark libraries express the same interaction with radio/button groups or segmented controls.
| Capability | VeanUI | Ant Design | Element Plus | Mantine | Naive UI | shadcn ToggleGroup |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — | — | ✅ |
| Single / multiple selection | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Controlled / uncontrolled | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Roving focus arrow keys | ✅ | — | — | — | — | ✅ |
| Loop navigation | ✅ | — | — | — | — | ✅ |
| RTL-aware arrow direction | ✅ | — | — | — | — | ✅ |
aria-pressed + data-state | ✅ | — | — | — | — | ✅ |
| Orientation (horizontal/vertical) | ✅ | — | ✅ | ✅ | — | ✅ |
| Variants × sizes × colors | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Hidden-input form submission | ✅ | — | — | — | — | — |
| Clearable single deselect | ✅ | ✅ | — | — | — | — |
| Disabled (group + item) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Cautions
rovingFocus,loop, andclearabledefault totrue. DisablingrovingFocusfalls back to a plainrole="group"with no arrow-key navigation.- Group-level
disableddisables every item; item-leveldisabledonly affects that item, and the two are combined (group || item). - In single mode, clicking the selected item again emits
update:modelValuewithundefined(unless:clearable="false") — handle theundefinedvalue in the parent. - Form submission requires
name;requiredonly marks the hidden input, it does not validate. - For icon-only items, add
aria-labelso the button has an accessible name. - In a
form, the hidden input is only rendered when the group is a form control andnameis set.
FAQ
Single or multiple selection?
Single is the default. Pass multiple to allow several items at once — modelValue/defaultValue then become arrays and the generic M is inferred from them.
How do I allow deselecting the selected item in single mode?
clearable defaults to true, so clicking the active item clears it and emits undefined. Set :clearable="false" to keep a selection always present.
How do I make arrow keys wrap around?
Keep loop (default true) and the focus wraps from the last to the first item and vice versa. Disabled items are skipped.
What is the difference between SToggleGroup and SToggle?
SToggleGroup coordinates a set of items: it owns single/multiple selection, roving-focus keyboard navigation, and shared aria-pressed state. SToggle is a single standalone toggle with no group coordination.
How do I render the group vertically?
Set orientation="vertical" — the layout switches to a stacked column and arrow navigation follows the vertical axis.