1
ComponentsActions

Toggle

A two-state pressed button for actions such as bookmarks, mute and text formatting.

Purpose

Use Toggle for one two-state button action such as bookmark, mute or text formatting.

Pressed state

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

export function Example() {
  return <Toggle defaultPressed>Bold</Toggle>;
}

Installation

With the Siteplane registry alias configured, add the component and import the installed source from your app.

CLI

pnpm dlx shadcn@4.16.1 add @siteplane/toggle

Import

import { Toggle } from "@/components/ui/toggle";
import { Button } from "@/components/ui/button";
import { BoldIcon, BookmarkIcon, StarIcon, Volume2Icon, VolumeXIcon } from "lucide-react";

Need the machine-readable source metadata? View registry JSON.

Usage

Toggle is a pressed/unpressed button. Use ToggleGroup when the controls are related choices.

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

export function Example() {
  return <Toggle defaultPressed>Bold</Toggle>;
}

Examples

Variants, sizes, icon labels, states and controlled usage are props of the same primitive.

Variants

<Toggle defaultPressed>Default</Toggle>
<Toggle defaultPressed variant="outline">Outline</Toggle>

Sizes

<Toggle aria-label="Small toggle" size="sm" variant="outline"><StarIcon /></Toggle>
<Toggle aria-label="Default toggle" variant="outline"><StarIcon /></Toggle>
<Toggle aria-label="Large toggle" size="lg" variant="outline"><StarIcon /></Toggle>
<Toggle aria-label="Extra large toggle" size="xl" variant="outline"><StarIcon /></Toggle>

Icon only

Icon-only toggles need an aria-label because there is no visible text.

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

Icon + text

<Toggle variant="outline">
  <ItalicIcon />
  Italic
</Toggle>

States

<Toggle>Off</Toggle>
<Toggle defaultPressed>On</Toggle>
<Toggle defaultPressed disabled>Disabled</Toggle>

Controlled

pressed and onPressedChange drive the icon and label from outside state.

const [muted, setMuted] = useState(false);

<Toggle
  aria-label={muted ? "Unmute audio" : "Mute audio"}
  onPressedChange={setMuted}
  pressed={muted}
  variant="outline"
>
  {muted ? <VolumeXIcon /> : <Volume2Icon />}
  {muted ? "Muted" : "Sound"}
</Toggle>

API Reference

The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.

  • Toggle accepts controlled pressed, uncontrolled defaultPressed, onPressedChange, native button props and Base UI's render contract.
  • variant="default" | "outline" and size="sm" | "default" | "lg" | "xl" are the complete visual variant set.
  • Base UI mirrors the pressed state to aria-pressed and data-pressed.

Motion

Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.

  • Toggle uses the shared button-like hover and press feedback while keeping the persistent pressed state visually distinct.
  • Reduced motion removes non-essential scale feedback without changing selection state.

Accessibility

  • Give icon-only Toggles an accessible label and keep controlled labels synchronized with state.
  • Use Toggle for one action, Toggle Group for related choices and Switch for a direct settings preference.
  • Preserve aria-pressed instead of expressing state with color alone.

Implementation Guidance

  • Use only the documented variants and sizes.
  • Keep hover, active and persistent pressed state separate.
  • Do not replace the Base UI pressed-state contract with a local click-state wrapper.

On This Page