Back to catalog
Component detail entry
Forms
@vean/ui
SToggleGroup

ToggleGroup

ToggleGroup belongs to the Forms category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

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 — multiple switches between one and many selected items, with a type-safe generic value (M extends boolean, T extends DefinedValue)
  • 🎚 Controlled / uncontrolled — v-model and defaultValue (scalar or array) backed by useControllableState
  • ⌨️ Roving focus keyboard navigation — arrow keys move focus between items, loop wraps 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 Button prop surface (as/asChild, type, item-level disabled), and slot props exposing pressed / disabled
  • 📝 Form integration — name/required render a hidden input so the selection submits with the owning form
  • 🧩 ui per-slot class overrides (root / item)

Component family

  • SToggleGroup — the group root that manages selection state, orientation, and roving focus
  • SToggleGroupItem — an individual toggleable button; pass a unique value that identifies it in the group

Demos

Basic

API

Aria Layer

3

ToggleGroup<M, T>

19 Props1 Emits
Props
PropTypeDefaultDescription
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 NameParametersDescription
update:modelValue
M extends true ? T[] : T
—

ToggleGroupItem<T>

5 Props
Props
PropTypeDefaultDescription
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>

14 Props1 Emits
Props
PropTypeDefaultDescription
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 NameParametersDescription
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.

CapabilityVeanUIAnt DesignElement PlusMantineNaive UIshadcn 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, and clearable default to true. Disabling rovingFocus falls back to a plain role="group" with no arrow-key navigation.
  • Group-level disabled disables every item; item-level disabled only affects that item, and the two are combined (group || item).
  • In single mode, clicking the selected item again emits update:modelValue with undefined (unless :clearable="false") — handle the undefined value in the parent.
  • Form submission requires name; required only marks the hidden input, it does not validate.
  • For icon-only items, add aria-label so the button has an accessible name.
  • In a form, the hidden input is only rendered when the group is a form control and name is 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.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.30.0

2026-08-20

Compare release

Style

fix demo class

Scope: toggle-groupAuthors: soybeanjsView commite27e0

Style

fix demo class

Scope: toggle-groupAuthors: soybeanjsView commite27e0

v0.19.0

2026-05-11

Compare release

Optimization

replace SToggleGroupItem import with headless component and remove unused file

Scope: toggle-groupAuthors: soybeanfeView commit45418

v0.15.0

2026-04-26

Compare release

Optimization

update variant options and remove outline example

Scope: toggle-groupAuthors: soybeanjsView commit34cf7

Optimization

update variant options and remove outline example

Scope: toggle-groupAuthors: soybeanjsView commit34cf7