Inputs/Toggle

Toggle

A two-state button that can be either on or off.

Themed

When to Use

Use Toggle when you need to:

  • Let users switch a single option on or off (bold, italic, bookmark)
  • Provide a two-state button in a toolbar or action bar
  • Create stateful icon buttons that visually reflect their pressed state
  • Build formatting controls for rich-text editors

When Not to Use

  • Multiple related options that work together - use Toggle Group
  • Settings or preferences with on/off semantics - use Switch
  • One-shot actions like submit or navigate - use Button
  • Binary choices in forms (agree/disagree) - use Checkbox

Default

A toggle button with custom styling when pressed. Uses data-[state=on] for pressed state styling.

Variants

Available style variants: default (transparent, no border) and outline (visible border with shadow).

Default
Outline

Outline

Outline variant with a visible border, ideal for toolbar-style controls.

With Text

Toggle with both an icon and text label. The gap between icon and text is handled automatically.

Sizes

Available size options: sm (32px), default (36px), and lg (40px).

Small
Default
Large

Disabled

Disabled toggles prevent user interaction. Both unpressed and pressed states are shown.

Controlled

Controlled toggle with external state management via pressed and onPressedChange props.

Not starred

UX & Design Guidelines

Visual Hierarchy

Use variant="default" for toolbar toggles that sit alongside other controls, and variant="outline" when the toggle needs to stand on its own or requires a visible boundary. The pressed state uses bg-accent with text-accent-foreground to clearly differentiate on and off states.

Spacing & Layout

When grouping toggles in a toolbar, use gap-1 for tight formatting toolbars or gap-2 for standard spacing. For related toggle groups, prefer the Toggle Group component which handles spacing and selection logic automatically.

Responsive Behavior

On mobile, consider using size="lg" for better touch targets (minimum 40px). Icon-only toggles should include text labels on larger screens when space permits. Use the min-w-* property to maintain consistent square dimensions for icon-only toggles.

Color & Contrast

The default pressed state uses bg-accent with text-accent-foreground for sufficient contrast. When customizing pressed styles with data-[state=on]: classes, ensure the on/off states have distinct visual contrast. Disabled states reduce opacity to 50% while maintaining readability.

Accessibility

Keyboard Navigation

  • Tab — Move focus to/from the toggle
  • Space — Toggle the pressed state
  • Enter — Toggle the pressed state

Screen Reader Support

  • Built on Radix UI Toggle primitive with full ARIA support
  • Automatically manages aria-pressed state (true/false)
  • Icon-only toggles require aria-label for screen reader users
  • Disabled state is announced via the disabled attribute

Focus Management

Visible focus ring with 3px width using focus-visible:ring-[3px]. Focus states meet WCAG 2.1 Level AA requirements. The ring uses ring-ring/50 with border-ring for consistent theming.

Touch Targets

Default size is 36px height (h-9) with min-w-9, meeting minimum touch target recommendations. Use size="lg" (40px) for critical touch interactions. The min-w-* property ensures square hit areas for icon-only toggles.

ARIA Attributes

{/* Icon-only toggle — requires aria-label */}
<Toggle aria-label="Toggle bold">
  <Bold />
</Toggle>

{/* Toggle with visible text — label is read automatically */}
<Toggle aria-label="Toggle italic">
  <Italic />
  Italic
</Toggle>

{/* Controlled toggle with live region for state feedback */}
<Toggle
  pressed={isBold}
  onPressedChange={setIsBold}
  aria-label="Toggle bold"
>
  <Bold />
</Toggle>
<span role="status" className="sr-only">
  {isBold ? "Bold enabled" : "Bold disabled"}
</span>

API Reference

The Toggle component accepts the following props in addition to standard button attributes.

PropTypeDefaultDescription
variant"default" | "outline""default"The visual style variant of the toggle.
size"default" | "sm" | "lg""default"The size of the toggle button.
pressedbooleanThe controlled pressed state of the toggle.
defaultPressedbooleanfalseThe default pressed state when initially rendered (uncontrolled).
onPressedChange(pressed: boolean) => voidEvent handler called when the pressed state changes.
disabledbooleanfalseWhen true, prevents user interaction and applies disabled styles.
classNamestringAdditional CSS classes to apply to the toggle.