Primitives
Primitive

Toggle

Two-state button for toggling between on and off

A toggle is a two-state button that stays pressed when on. Use it for a single on/off control like bold, mute, or pin. For a set of mutually exclusive or multi-select toggles, use Toggle Group; for a labeled settings switch, use Switch.

Preview

Installation

Usage

Examples

Sizes

Use size to set the toggle's height and padding.

SizeDescription
smCompact, for dense toolbars.
defaultThe standard height.
lgTaller, for prominent controls.

With Text

Place a text label alongside the icon inside the toggle.

Solid Variant

Set variant="solid" for a filled button: a muted plate when off that insets when on (the same treatment the detached toggle group gives its cells).

Outline Variant

Set variant="outline" to frame the toggle with a border.

VariantDescription
ghostBorderless. Transparent when off, filled when on. Default.
solidMuted plate when off; insets to the selected overlay when on.
outlineFramed with a border. Fills when on.

Custom Colors

The toggle paints its fill from CSS variables, one per state:

VariableState
--tgl-bgOff.
--tgl-bg-hoverOff and hovered.
--tgl-bg-activeOff and held down. Falls back to hover.
--tgl-bg-selectedOn.
--tgl-borderBorder color, in every state.

Each variant sets them and the toggle switches between them internally, so recoloring the fill is just overriding the variables, with no hover: or data-pressed: prefixes needed. Override the variables instead of bg-* classes: root-level bg-* paints behind the fill layer, so it is hidden by opaque variants and blended by transparent ones, which is rarely what you want. The label color is not tokenized, so it stays a normal state-prefixed text class:

Custom property values can't take Tailwind's /10 opacity shorthand, so build a translucent tint with color-mix instead:

Any variable you don't override keeps the variant's color for that state. The solid variant is the exception: its plate is --tgl-bg and its hover and selected states composite a translucent overlay on top of that plate, so retint it through --tgl-bg rather than the per-state variables.

The border lives on the toggle's paint pseudo-element, so before: classes restyle it, for example before:border-dashed or before:border-2. Only outline sets a visible --tgl-border, so on the other variants pair those classes with a color: [--tgl-border:var(--border)] before:border-dashed. Cells in an attached solid or ghost group are the exception, since the group strips their borders to keep the track seamless.

Controlled

Use pressed and onPressedChange to drive the toggle state yourself.

Disabled State

Use disabled to prevent interaction.

Accessibility

Label icon-only toggles

An icon-only toggle has no text for a screen reader to announce. Give it an aria-label describing the action it controls.

API Reference

The Toggle component is built on top of Base UI's Toggle. All Base UI props are supported. The documentation below only covers custom props and modified defaults specific to our implementation.

For the complete Base UI API, see the Base UI Toggle documentation.

Custom Props

Prop