Light

Toggle

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

Spec · from metadata

When to use

  • Toggling a formatting option (bold, italic, etc.)
  • Toolbar actions with on/off state
  • Single option toggle (e.g., mute, favorite)

When not to use

  • Binary setting — use Switch instead
  • Group of mutually exclusive options — use ToggleGroup instead
  • Navigation actions — use Button instead
  • Form checkbox — use Checkbox instead

Variants

PropValuesDefaultDescription
variantdefaultoutlinedefaultdefault has transparent background; outline adds border and shadow.
sizedefaultsmlgdefaultControls height: sm=32px, default=36px, lg=40px.

Anti-patterns

Avoid<Toggle><BoldIcon /></Toggle>
Prefer<Toggle aria-label="Toggle bold"><BoldIcon /></Toggle>

Icon-only toggles must have an aria-label for screen readers.

Accessibility

  • Required ARIAaria-label (when icon-only)aria-pressed (auto)
  • Min touch target32px
  • Screen readerBuilt on Radix Toggle. Announces pressed/unpressed state via aria-pressed.
  • ContrastPressed state uses bg-accent/text-accent-foreground for clear visual feedback.

Token bindings

TokenCategoryUsage
accentcolorPressed state background
accent-foregroundcolorPressed state text
mutedcolorHover background
inputcolorOutline variant border
rounded-mdradiusBorder radius

Import

import { Toggle } from "@timelycare/helix-ui"

Props

interface ToggleProps {
  pressed?: boolean
  onPressedChange?: (pressed: boolean) => void
  variant?: "default" | "outline"
  size?: "default" | "sm" | "lg"
  disabled?: boolean
  className?: string
  children: React.ReactNode
}

Structure

PartTailwind
Baseinline-flex items-center justify-center rounded-md gap-2 text-sm font-semibold text-foreground
Iconsize-4 (16px)
Texttext-sm font-semibold leading-normal text-foreground

Variants

VariantOff StateOn State
defaultbg-transparentbg-accent
outlineborder border-input bg-transparent shadow-xsbg-accent

Choosing a Variant

  • Default: Use for toolbars and compact controls
  • Outline: Use when you need a visible boundary in the off state

Sizes

SizeHeightPaddingUse For
smh-8 (32px)px-1.5Compact toolbars
defaulth-9 (36px)px-2Standard controls
lgh-10 (40px)px-2.5Prominent actions

Icons

Size: size-4 (16px)
Spacing: gap-2 (8px between icon and text)

<Toggle>
  <Bold className="size-4" />
</Toggle>

States

StateStyling
Default (off)bg-transparent
Hoverhover:bg-muted hover:text-muted-foreground
Focusring-[3px] ring-ring/50
Pressed (on)bg-accent text-accent-foreground
Disabledopacity-50 pointer-events-none

Common Patterns

Icon Only

<Toggle aria-label="Toggle bold">
  <Bold className="size-4" />
</Toggle>

With Text

<Toggle>
  <Italic className="size-4" />
  Italic
</Toggle>

Outline Variant

<Toggle variant="outline">
  <Underline className="size-4" />
</Toggle>

Text Only

<Toggle>Text</Toggle>

Accessibility

  • Built on Radix Toggle — handles keyboard and focus automatically
  • Keyboard: Enter/Space to toggle pressed state
  • Screen reader: announces pressed state via aria-pressed
  • Focus visible ring applied automatically

Gotchas

ProblemSolution
Toggle doesn't show pressed stateUse pressed prop for controlled state
Icon not centeredEnsure icon has size-4 class
No focus ring visibleCheck ring-ring color is defined

See Also


Last updated: February 9, 2026