VisorVisor
ComponentsForm

Toggle Group

A group of toggle buttons where one or multiple can be active. Built on Radix UI with CVA variants.

Variants

Sizes

Multiple Selection

Installation

npx visor add toggle-group

This copies two files into your project:

  • components/ui/toggle-group/toggle-group.tsx — the component
  • components/ui/toggle-group/toggle-group.module.css — the styles

Usage

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

<ToggleGroup type="single">
  <ToggleGroupItem value="a">A</ToggleGroupItem>
  <ToggleGroupItem value="b">B</ToggleGroupItem>
</ToggleGroup>

API Reference

ToggleGroupProps

PropTypeDefaultDescription
type*'single' | 'multiple'—Whether one or multiple items can be active at once.
variant'default' | 'outline''default'Visual style variant of the toggle group.
size'xs' | 'sm' | 'md' | 'lg''md'Size of the toggle items.
valuestring | string[]—Controlled active value(s).
onValueChange(value: string | string[]) => void—Callback when the active value changes.

Sub-components

ComponentElementPurpose
ToggleGroup<div>Root group container with variant/size context and optional sliding indicator
ToggleGroupItem<button>Individual toggle button inheriting variant and size from the group

Accessibility

  • Built on @radix-ui/react-toggle-group. A single-select group has role="radiogroup" with role="radio" items and aria-checked; a multi-select group stays a group of aria-pressed buttons
  • Keyboard focus draws a solid --border-focus ring at --focus-ring-width, offset by --focus-ring-offset, on every item
  • Provide an aria-label on <ToggleGroup> to describe the purpose of the group (e.g., "Text formatting", "View mode")
  • Keyboard: Arrow keys navigate between items within the group; Space/Enter toggles the focused item

Label Centering

The label is optically centred in any font: its line box is trimmed to the capital-height band, so capitals (not the font's ascent and descent) sit on the box centre, with the box size unchanged. Firefox keeps the previous rendering. Shared spec: docs/label-centering.md.