Skip to main content

ToggleGroup

Picks exactly one option from a short row of toggle buttons.

import { ToggleGroup } from "@/fragments/ui";Source

Preview

<ToggleGroup value={value} onChange={setValue}>
  <ToggleGroup.Item value="left">Left</ToggleGroup.Item>
  <ToggleGroup.Item value="center">Center</ToggleGroup.Item>
  <ToggleGroup.Item value="right">Right</ToggleGroup.Item>
</ToggleGroup>

Installation

npx @usefragments/cli add togglegroup

Writes src/fragments/ui/components/ToggleGroup plus what it imports, the globals stylesheet, and .fragments/registry-lock.json, then prints the packages to add. No account, no key.

Your own registry: publish from Fragments Cloud and add --registry org/name. Connect a workspace.

Anatomy

ToggleGroup is a compound: import the root and reach its parts through dot notation.

  • ToggleGroup.Item

Inset tonal rail; the selected segment lifts.

<ToggleGroup value={value} onChange={setValue}>
  <ToggleGroup.Item value="left">Left</ToggleGroup.Item>
  <ToggleGroup.Item value="center">Center</ToggleGroup.Item>
  <ToggleGroup.Item value="right">Right</ToggleGroup.Item>
</ToggleGroup>

Examples

Uncontrolled

defaultValue when nothing outside needs the selection.

<ToggleGroup defaultValue="list">
  <ToggleGroup.Item value="grid">Grid</ToggleGroup.Item>
  <ToggleGroup.Item value="list">List</ToggleGroup.Item>
</ToggleGroup>

Sizes

sm for toolbars, lg where the rail anchors a page.

import { Stack } from '@/components/Stack';

<Stack direction="column" gap="md" align="start">
  <ToggleGroup defaultValue="a" size="sm">
    <ToggleGroup.Item value="a">Small</ToggleGroup.Item>
    <ToggleGroup.Item value="b">Rail</ToggleGroup.Item>

View Switcher

Icon-only modes, each named for screen readers.

import { SquaresFour as GridIcon, ListBullets as ListIcon } from '@phosphor-icons/react';

<ToggleGroup value={view} onChange={setView} size="sm">
  <ToggleGroup.Item value="grid" aria-label="Grid view">
    <GridIcon aria-hidden />
  </ToggleGroup.Item>

Disabled Item

One option locked out; the rest stay reachable.

<ToggleGroup value={value} onChange={setValue}>
  <ToggleGroup.Item value="basic">Basic</ToggleGroup.Item>
  <ToggleGroup.Item value="pro">Pro</ToggleGroup.Item>
  <ToggleGroup.Item value="enterprise" disabled>Enterprise</ToggleGroup.Item>
</ToggleGroup>

API

Component props
Prop
Type
Default
Description
valuestringNot setCurrently selected value
defaultValuestringNot setInitial selected value (uncontrolled)
onChangefunctionNot setCalled with new value when selection changes
onValueChangefunctionNot setAlias for onChange (Radix convention): (value: string) => void
childrenRequirednodeNot setToggleGroup.Item components
variantenumsoftghostoutlinesoftChrome: soft is the filled rail, ghost the open pill cluster, outline the connected bordered segments
sizeenumsmmdlg"md"Size variant
gapenumsmnonexsNot setGap between items in the ghost variant. Connected variants intentionally ignore gaps.
selectionModeenumsinglesingleSelection behavior

Accessibility

  • The group is a radiogroup; each item is a radio with aria-checked
  • Arrow keys move between items, Tab enters and leaves the group
  • Icon-only items still need an aria-label
  • Focus stays visible on the selected item

Guidance

Use when

  • Switching between mutually exclusive views or modes
  • Choosing one of two to five options
  • View switchers and segmented filters

Avoid when

  • More than one can be picked — use a Checkbox group
  • More than five options — use Select or RadioGroup
  • Moving between pages — use Tabs
  • A single on/off — use Switch
  • RadioGroupalternativeRadioGroup for form-style single selection
  • TabsalternativeTabs for content panel switching
  • SwitchsiblingSwitch for single on/off control

Next steps