Skip to content
Component installs need the registry setup— the Base UI shadcn project, the @vegastack namespace and the Cloudflare Access service token.
VegaStack Design

Toggle

A two-state button that can be pressed on or off — bold/italic, mute, pin.

Status
stable
Since
0.1.0
Accessibility pattern
toggle button (aria-pressed)

Last updated

Install

Add Toggle from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.

pnpm dlx shadcn@latest add @vegastack/toggle

Usage

import { Toggle } from "@/components/ui/toggle";

<Toggle aria-label="Toggle bold">
  <Bold />
</Toggle>;

Toggle is uncontrolled by default — pass defaultPressed for an initial value, or control it with pressed + onPressedChange.

const [bold, setBold] = useState(false);

<Toggle pressed={bold} onPressedChange={setBold} aria-label="Toggle bold">
  <Bold />
</Toggle>;

Examples

Sizes & States

One look (no variant prop) in three sizes (sm, md, lg). Icons compose as children via lucide-react. The toggle is a ghost at rest; when pressed it takes the system's one selected-chip look — an evident neutral ink tint with a hairline, never a brand colour — so the "on" state reads clearly. That look is the shared selectedChipVariants recipe, so a pressed Toggle, a pressed ToggleGroup item, a Segmented chip and an active pill tab are the same thing by construction; a pressed toggle also still hovers (the tint strengthens) and still presses (it drops back, previewing the release). The states row shows off, on (defaultPressed), disabled, and disabled+on. A genuine selection (single/multi) belongs in ToggleGroup, whose pressed items take the exact same fill.

Playground

Try the three sizes and the disabled and default-pressed states, then copy the generated JSX.

<Toggle aria-label="Toggle bold">
  <Bold />
</Toggle>

API Reference

PropTypeDefaultDescription
size"lg" | "md" | "sm"

Data attributes and CSS variables on Toggle

AttributeValues
data-sizemirrors a prop or state value
data-slot"toggle"

Accessibility

  • Renders a native <button> with aria-pressed reflecting the on/off state — keyboard Enter / Space toggle it.
  • The pressed state is also exposed as data-pressed for styling; never style state with outline: none.
  • The component adds no custom ring class of its own and never sets outline: none, so keyboard focus shows the design system's global 2px :focus-visible ring (outline-ring) — keep it visible; never remove it with outline: none.
  • Icon-only toggles must have an aria-label (or visible text) so the action is announced.
  • disabled removes the toggle from the tab order and blocks interaction.
ContractStates tested
Behaviourdefault, disabled, error, invalid, pressed
Accessibilityinvalid, labeled, pressed
Visualdefault, hover, disabled, invalid, error

Do / Don't

Do
Use a Toggle for a binary on/off control that stays in the UI, like a bold or mute button — and give icon-only toggles an aria-label.
Don't
Use a Toggle for a one-shot action (use a Button) or for mutually-exclusive options (use a ToggleGroup or Radio Group).

On this page