Experience System
Components

Toggle Group

Related two-state toggles with single or multiple selection, separators, and toolbar-aligned styling.

Installation

The components are exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.

Composition

Use ToggleGroup as the root, ToggleGroupItem for each option, and optional ToggleGroupSeparator between items:

ToggleGroup
├── ToggleGroupItem
├── ToggleGroupSeparator (optional)
├── ToggleGroupItem
└── …

Each ToggleGroupItem must have a unique value. dir on the root defaults from ThemeProvider so keyboard and layout follow reading direction. See Radix Toggle Group.

Usage

import { ToggleGroup, ToggleGroupItem, ToggleGroupSeparator } from '@by/experience-system';

ToggleGroup and its parts are client components ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.

<ToggleGroup type="multiple" defaultValue={['bold']} aria-label="Text style">
  <ToggleGroupItem value="bold" aria-label="Bold">
    B
  </ToggleGroupItem>
  <ToggleGroupSeparator />
  <ToggleGroupItem value="italic" aria-label="Italic">
    I
  </ToggleGroupItem>
</ToggleGroup>

Examples

Overview

type="multiple" with separators and variant="ghost" (same preview as at the top of the page).

Label with icon

segment="label" and variant="outline" for icon + text items.

Variants

outline and ghost groups side by side.

Outline
Ghost

Sizes

sm, md, and lg with variant="outline".

Small
Medium
Large

Vertical

orientation="vertical" with spacing={1} for outline and ghost.

Outline
Ghost

API Reference

The tables below mirror the Radix UI Toggle Group API for Root and Item, plus Experience System extensions. dir on ToggleGroup follows ThemeProvider unless overridden.

ToggleGroup

PropTypeDefault
asChildbooleanfalse
typesingle | multiple— (required)
valuestring or string[]
defaultValuestring or string[]
onValueChange(value: string | string[]) => void
disabledbooleanfalse
rovingFocusbooleantrue
orientationhorizontal | vertical
loopbooleantrue
dirltr | rtlFrom ThemeProvider unless overridden
variantoutline | ghostghost
sizesm | md | lg and legacy aliases (see ToggleGroup source)md
spacing0 | 1 | 2 | 3 | 40
Data attributeValues
data-slottoggle-group
data-variantoutline | ghost
data-sizesm | md | lg
data-spacing0 | 1 | 2 | 3 | 4
data-orientationhorizontal | vertical

ToggleGroupItem

PropTypeDefault
asChildbooleanfalse
valuestring— (required)
disabledboolean
variantoutline | ghostFrom group context
sizesm | md | lg and legacy aliasesFrom group context
segmenticon | labelicon
Data attributeValues
data-slottoggle-group-item
data-variantoutline | ghost
data-sizesm | md | lg
data-segmenticon | label
data-spacingmirrors group spacing
data-stateon | off
data-disabledPresent when disabled
data-orientationhorizontal | vertical

ToggleGroupSeparator

Renders a decorative Separator between items. orientation defaults to a bar across the group axis (vertical divider in a horizontal group, horizontal rule in a vertical group).

PropTypeDefault
orientationhorizontal | verticalFrom group orientation
classNamestring

Also forwards Separator props except the Experience System replaces fixed orientation typing; see ToggleGroupSeparatorProps in the package.

Data attributeValues
data-slottoggle-group-separator

Accessibility

Use an aria-label (or aria-labelledby) on ToggleGroup; give each ToggleGroupItem a name (aria-label when the content is icon-only). Radix uses roving tabindex inside the group. See Radix Toggle Group — accessibility.

Keyboard interactions

KeyDescription
TabMoves focus to the pressed item or the first item in the group.
SpaceToggles the focused item’s pressed state.
EnterToggles the focused item’s pressed state.
ArrowRight / ArrowDownMoves focus to the next item (respects orientation and reading direction).
ArrowLeft / ArrowUpMoves focus to the previous item.
HomeMoves focus to the first item.
EndMoves focus to the last item.

Source in the repo: packages/experience-system/src/components/ToggleGroup/ToggleGroup.tsx. Agent-oriented contracts: packages/experience-system/src/components/ToggleGroup/ToggleGroup.instructions.md.