Skip to content

ComponentsButtons

Toggle Button Group

A set of toggle buttons with single or multiple selection. Use it as an attached button bar, a segmented control or a spaced toolbar; it's one tab stop with arrow-key navigation, and passes its variant and size down to every button.

React AriaSource

Installation

pnpm dlx shadcn@latest add @desyne/toggle-button-group

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import { ToggleButton } from "@/components/ui/toggle-button";
import { ToggleButtonGroup } from "@/components/ui/toggle-button-group";
tsx
<ToggleButtonGroup
  aria-label="View"
  defaultSelectedKeys={["list"]}
  disallowEmptySelection
>
  <ToggleButton id="list">List</ToggleButton>
  <ToggleButton id="board">Board</ToggleButton>
</ToggleButtonGroup>

Give every ToggleButton an id: that's the key used in selectedKeys. The group passes its variant and size to its buttons, so you don't repeat them on each one.

Add disallowEmptySelection for segmented controls

By default, pressing the selected button in a single-selection group deselects it, leaving nothing selected. For view switchers, tabs-like controls and billing toggles, set disallowEmptySelection so one option is always active.

When to use

  • Toggle Button Group — a small set (2–6) of options that apply immediately, like a view switcher, a time range or text formatting.
  • Toggle Button — a single, independent on/off control.
  • Radio Group — a labelled choice in a form, especially with descriptions.
  • Tabs — switching between panels of content, with a tab panel for each option.
  • Select — more options than fit on one line.

Anatomy

tsx
<ToggleButtonGroup>        {/* toolbar or radiogroup, passes variant + size */}
  <ToggleButton id="…" />  {/* one per option */}
</ToggleButtonGroup>
PartRendersNotes
ToggleButtonGroup<div role="radiogroup"> or <div role="toolbar">radiogroup for selectionMode="single", toolbar for "multiple". Nested in a React Aria Toolbar, it becomes role="group". Carries data-slot="toggle-button-group".
ToggleButton<button>An option. role="radio" in single mode, aria-pressed in multiple mode. See Toggle Button.

Examples

Variants

attached (default) joins bordered buttons into one bar. segmented is a pill track with a raised selection. spaced keeps borderless buttons separate with a small gap, which suits toolbars. The group sets its buttons to outline, segmented and default respectively.

attached
segmented
spaced

Segmented

A segmented control for switching views, time ranges or modes. Pair it with disallowEmptySelection so an option is always selected.

Sizes

size is passed to every button, from xs (24px) to lg (40px). A size set on an individual ToggleButton wins over the group's.

With icons

Icons combine with labels in segmented controls. Icon-only buttons need an aria-label each.

Multiple selection

selectionMode="multiple" lets any number of buttons be on at once, like a formatting bar. The group is then a toolbar and each button announces aria-pressed.

Vertical

orientation="vertical" stacks the buttons and switches keyboard navigation to ↑ / ↓. All three variants support it.

Controlled

Use selectedKeys and onSelectionChange to own the selection. The callback receives a Set of keys in both single and multiple mode. Here a weekday picker uses spaced with outline buttons set directly on each item.

Repeats every Monday, Wednesday, Friday.

Disabled

isDisabled on the group disables every button; isDisabled on a single ToggleButton disables just that option, for example a format that isn't available on the current plan.

Recipes

View switcher

A small icon-only segmented control in a section header that switches a file list between grid and list layouts.

Shared files

  • Brand guidelines.pdf4.2 MB · Today
  • Q3 board deck.key18.7 MB · Yesterday
  • Customer interviews.docx310 KB · Mon
  • Pricing model.xlsx96 KB · Sep 12

Editor toolbar

Several groups inside one React Aria Toolbar: multiple selection for styles, single selection for alignment, with Tooltips that show shortcuts. The toolbar owns arrow-key navigation across all groups, so the whole bar is one tab stop.

Billing toggle

A full-width segmented control (*:flex-1) that switches a pricing card between monthly and yearly billing, with a Badge for the discount.

Pro

$16per seat / month

Billed $192 yearly

  • Unlimited projects
  • Version history
  • SSO & audit log

Accessibility

  • In single-selection mode the group is a radiogroup and each button is a radio with aria-checked; in multiple mode it's a toolbar and each button uses aria-pressed.
  • The group is labelled with aria-label or aria-labelledby. Always describe what it controls ("Text alignment", "View as").
  • Arrow keys move focus between buttons. Tab leaves the group, and focus returns to the last focused button when you tab back in.
  • Inside a React Aria Toolbar, the group becomes a group and the toolbar handles arrow keys, so several groups share one tab stop.
  • Arrow-key direction is reversed in right-to-left locales for horizontal groups.

Keyboard

KeyAction
Tab / Shift+TabMoves focus into or out of the group
← / →Moves focus between buttons (horizontal)
↑ / ↓Moves focus between buttons (vertical)
Space / EnterToggles the focused button

Styling

Data attributes

On the ToggleButtonGroup:

AttributePresent when
data-orientationAlways, "horizontal" or "vertical"; the variants use it to switch between row and column layouts
data-disabledisDisabled is true
data-slot="toggle-button-group"Always

Each ToggleButton has the usual data-selected, data-hovered, data-pressed, data-focus-visible and data-disabled attributes. See Toggle Button.

Customizing

  • className on the group styles the container. Use child selectors to style the buttons in bulk, e.g. *:flex-1 for equal-width segments or w-full for a full-width bar.
  • attached strips the buttons' radius and shadow and overlaps borders by 1px; the selected button is raised with z-[1] so its brand border stays visible.
  • To use a different item style than the group's default, set variant on each ToggleButton; it overrides the value from context.

Render props

className accepts a function of the group's state:

tsx
<ToggleButtonGroup
  className={({ orientation }) => (orientation === "vertical" ? "w-40" : "")}
/>

API Reference

ToggleButtonGroup

Prop

Type

Also accepts every prop of React Aria's ToggleButtonGroup.

ToggleButton

Inside a group, id is required and isSelected, defaultSelected and onChange are ignored in favor of the group's selection. See the Toggle Button API for the rest.

  • Toggle Button — the individual buttons.
  • Radio Group — single choice in a form.
  • Tabs — switch between panels of content.
  • Button — attach plain action buttons with a React Aria Group.