Skip to content

ComponentsButtons

Toggle Button

A button that switches between on and off, like bold, mute or star. Announced as a pressed toggle, works with mouse, touch and keyboard, and picks up its style from a surrounding toggle button group.

React AriaSource

Installation

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

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

Usage

tsx
import { ToggleButton } from "@/components/ui/toggle-button";
tsx
<ToggleButton aria-label="Bold" defaultSelected>
  <BoldIcon />
</ToggleButton>

The label describes the action, not the state

A toggle button is announced with aria-pressed, so screen readers already say whether it is on. Keep the label constant ("Mute", "Bold") and let the pressed state carry the meaning. Swapping the label to "Unmute" while it is pressed reads as "Unmute, pressed", which is ambiguous.

When to use

  • Toggle button — an on/off state that applies immediately and persists, usually in a toolbar: bold, mute, pin, star.
  • Toggle Button Group — a set of related toggles, with single selection (a segmented control) or multiple selection (a formatting bar).
  • Switch — a labelled on/off setting in a form or settings list.
  • Checkbox — a choice that is submitted with a form.
  • Button — a one-off action with no persistent state.

Anatomy

A toggle button is a single element. Icons and text are plain children, sized and spaced for you.

tsx
<ToggleButton>
  <Icon />   {/* optional, auto-sized */}
  Label
</ToggleButton>
PartRendersNotes
ToggleButton<button aria-pressed>Root. Carries data-slot="toggle-button" and all state attributes. Inside a single-selection group it becomes role="radio" with aria-checked.
Icon<svg>Sized size-4 (size-3 / size-3.5 for xs / sm) unless you pass a size-* class.

Examples

Variants

default is borderless and fills with the accent color when selected, which suits toolbars. outline has a border and turns brand-tinted when selected, which reads better as a standalone control. A third variant, segmented, is applied automatically inside a segmented ToggleButtonGroup.

default
outline

With icon and label

Put an icon before the label for standalone toggles like Star, Pin or Watch. The label keeps the control understandable without a tooltip.

Sizes

md (32px) is the default. xs and sm fit dense toolbars and table rows; lg suits touch-first controls like call or player bars. Every size has a matching minimum width, so icon-only toggles stay square.

Controlled

Use isSelected and onChange to own the state, for example to persist it or to react to it elsewhere on the page. Use defaultSelected when the button can manage itself.

Notifications for #design are on.

Render props

children and className accept a function of the button's state. Use it to fill or swap the icon for the selected state without lifting state up, while the label stays the same.

With tooltip

Icon-only toggles need an aria-label. Wrap them in a TooltipTrigger so mouse users see the same label.

Disabled

isDisabled removes the button from the tab order and keeps its current state visible, so users can still see whether it is on.

Custom selected style

Style the selected state with Tailwind's data-selected: variant. Here the icon fills in and takes the destructive or brand color instead of the default accent background.

Recipes

Post actions

A like toggle with a live count and a save toggle, next to a regular comment button. The accessible label includes the count so it's announced too.

MC

Maya Chen

2 hours ago

Shipped the new onboarding checklist today. Activation is up 14% in the first week — huge thanks to everyone who tested the drafts.

Media player

A compact player bar mixing toggle buttons (like, shuffle, play/pause, repeat) with plain buttons (previous, next). The play toggle uses a render prop to swap icons.

Midnight Drive

Lumen Avenue · Night Transit

Filter chips

Rounded outline toggles that each switch a filter on or off, driving a filtered list. Use independent toggles like this when filters combine freely; use a ToggleButtonGroup with selectionMode="multiple" when you want the group to be one keyboard stop.

  • Priya RamanQ3 roadmap review
  • Jonas Weber@you can you check the invoice?

Accessibility

  • Renders a native <button> with aria-pressed, so it is announced as a toggle button along with its pressed state.
  • Inside a single-selection ToggleButtonGroup, React Aria switches it to role="radio" with aria-checked.
  • Icon-only toggles must have an aria-label (or aria-labelledby). Keep the label the same in both states.
  • The focus ring only appears for keyboard focus (data-focus-visible).
  • isDisabled sets the native disabled attribute and removes the button from the tab order.

Keyboard

KeyAction
TabMoves focus to the button
Space / EnterToggles the button

Styling

Data attributes

Style states with Tailwind's data variants, e.g. data-selected:text-brand.

AttributePresent when
data-selectedThe button is on
data-hoveredHovered with a mouse or pen (never on touch)
data-pressedBeing pressed
data-focusedFocused by any means
data-focus-visibleFocused with the keyboard
data-disabledisDisabled is true (directly or from the group)
data-slot="toggle-button"Always

Render props

className and children also accept a function of the button's state:

tsx
<ToggleButton
  aria-label="Mute"
  className={({ isSelected }) => (isSelected ? "text-destructive" : "")}
>
  {({ isSelected }) => (isSelected ? <VolumeXIcon /> : <Volume2Icon />)}
</ToggleButton>

toggleVariants

The tailwind-variants function behind the component. Use it to give another element the toggle look, or to extend the variants.

tsx
import { toggleVariants } from "@/components/ui/toggle-button";

toggleVariants({ variant: "outline", size: "sm" });

ToggleGroupStyleContext is also exported. ToggleButtonGroup uses it to pass variant and size down; props set directly on a ToggleButton win over the context.

API Reference

ToggleButton

Prop

Type

Also accepts every prop of React Aria's ToggleButton, including focus and keyboard handlers.

toggleVariants

Prop

Type

  • Toggle Button Group — single or multiple selection across a set of toggle buttons.
  • Button — for one-off actions.
  • Switch — a labelled on/off setting.
  • Tooltip — labels for icon-only toggles.