Skip to the content
BooleanPress UI

Form

Toggle

A button that stays pressed or not, for a view or filter option that applies at once.

Import

import { Toggle } from "@booleanpress/ui/toggle"

Usage

Name an icon-only toggle with aria-label; a toggle with text is named by its text. The name stays the same in both states: the pressed state is announced separately, so do not change the text to "Unpin" when it is pressed.

import { StarIcon } from "lucide-react"
import { Toggle } from "@booleanpress/ui/toggle"

export function StarToggle() {
  return (
    <Toggle variant="outline" aria-label="Star">
      <StarIcon />
    </Toggle>
  )
}

It is uncontrolled with defaultPressed, or controlled with pressed and onPressedChange. variant is default (no border) or outline; size is sm, default or lg. toggleVariants gives the same classes to another element. To switch a setting on or off, use Switch; for several related toggles, ToggleGroup; for an action that is not a state, Button.

Examples

Basic

An icon toggle named by aria-label, and a text toggle that starts pressed.

Variants and sizes

default and outline, each pressed, and the three sizes.

Controlled

pressed and onPressedChange keep the state in your code, here shown beside the toggle.

Disabled

A disabled toggle keeps its state, ignores clicks and keys, and leaves the tab order.

Accessibility

Semantics
A button with aria-pressed (true or false) and a data-state of on or off.
Labels
Icon-only toggles need aria-label. Keep the name constant across states.
Focus
It is in the tab order. The focus ring shows on keyboard focus, not on click.
Known limits
  • The small size is 32 px high and its minimum width is 32 px; the default is 36 px and the large 40 px. All meet WCAG 2.5.8's 24 px.
  • The pressed state is shown by a fill (--accent). An icon-only toggle in the default variant has no border, so keep it next to a label or group when the fill alone would be missed.

Keyboard

Keyboard
KeyBehaviour
SpacePresses or releases the toggle.
EnterPresses or releases the toggle.

API

Toggle

Renders Radix Toggle.Root and passes it every other prop.

Toggle props
PropTypeDefaultDescription
asChildbooleanRender the child element instead, with this part's behaviour and classes merged onto it.
defaultPressedbooleanThe state of the toggle when initially rendered. Use defaultPressed if you do not need to control the state of the toggle.
onPressedChange((pressed: boolean) => void)The callback that fires when the state of the toggle changes.
pressedbooleanThe controlled state of the toggle.

Also exported: toggleVariants, the class names of Toggle's variants and sizes (cva), to give another element the same look.

Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.

Data attributes: data-slot="toggle" (Toggle).

Theming

The pressed fill is --accent with --accent-foreground; hover is --muted. The outline variant uses --input for its border.

The tokens its classes read. Change their values in your theme, and it follows.

Theme tokens
TokenUsed for
--accentbackground
--accent-foregroundtext
--destructiveborder, focus ring
--inputborder
--mutedbackground
--muted-foregroundtext
--ringborder, focus ring