Skip to content

Toggle

Stable

A two-state button that turns a single option on or off and shows its current state.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/toggle.json

Usage

import { Toggle } from "@/components/ui/toggle"
<Toggle aria-label="Bold">
  <BoldIcon />
</Toggle>

Examples

Outline

The outline variant gives each toggle a visible boundary. Use it when toggles stand alone on a page rather than inside a toolbar.

With text

Pair the icon with a label when the icon alone could be ambiguous, or when the toggle is the only control of its kind on the page.

Sizes

Toggles share heights with buttons and inputs — sm 32, default 36, lg 40 — so they align in any toolbar.

Controlled

Control the state with pressed and onPressedChange when something else on the page depends on it. Here the icon and the helper text follow the state.

You'll be notified about new comments.

const [subscribed, setSubscribed] = React.useState(true)

<Toggle pressed={subscribed} onPressedChange={setSubscribed}>
  {subscribed ? <BellIcon data-icon="inline-start" /> : <BellOffIcon data-icon="inline-start" />}
  Notifications
</Toggle>

Disabled

Guidelines

When to use

  • For formatting and view options that apply immediately: bold, italic, word wrap, grid lines.
  • For marking something: Star, Pin, Watch — where the pressed state is the information.

When not to use

  • For settings that take effect as a preference — use a Switch, which reads as on/off rather than pressed.
  • For one choice among several — use a Toggle Group.
  • To trigger an action that doesn't have a persistent state — use a Button.

Label the option, not the action

A toggle's label names what it controls and stays the same in both states. The pressed styling carries the state; changing the text as well makes people unsure which state they're looking at.

Do.The label names the option; the pressed style shows it's on.
Don’t.An action verb that flips with the state is ambiguous: is it on or off?

Accessibility

  • Renders a native <button> with aria-pressed, so screen readers announce it as a toggle button with its current state.
  • Icon-only toggles need an aria-label. Don't include the state in the label — Bold, not Bold on — because aria-pressed already conveys it.
  • The pressed state is shown with a fill and a darker label, not by color alone; in forced-colors mode the system highlight takes over.
KeyBehavior
Tab
Moves focus to the toggle.
SpaceEnter
Toggles the pressed state.

API reference

Toggle

Renders a <button>. Accepts every prop of Base UI's Toggle.

PropTypeDefault
variant

Visual style. Outline adds a border and a raised fill.

"default" | "outline""default"
size

Height and padding, matching buttons and inputs.

"sm" | "default" | "lg""default"
pressed

The controlled pressed state.

booleanNo default
defaultPressed

The initial pressed state when uncontrolled.

booleanfalse
onPressedChange

Called when the pressed state changes.

(pressed: boolean, eventDetails) => voidNo default
disabled

Prevents interaction.

booleanfalse
value

Identifies the toggle inside a Toggle Group.

stringNo default
render

Replaces the rendered element while keeping behavior and styles.

ReactElement | (props, state) => ReactElementNo default

toggleVariants

The class generator, exported so other elements — like Toggle Group items — share the same styles.