Skip to main content
The Toggle component is a button that can be toggled on and off. It’s useful for binary options like bold text, italics, or favorites. Built on top of Base UI’s Toggle component with customizable variants and sizes.

Installation

npx shadcn@latest add @eo-n/toggle

Usage

Import the toggle component:
import { Toggle } from "@/components/ui/toggle";
<Toggle aria-label="Toggle bold">
  <Bold className="size-4" />
</Toggle>

API Reference

Toggle

Props Extends React.ComponentProps<typeof ToggleRoot> from Base UI.
PropTypeDefaultDescription
variant"default" | "outline""default"The visual style variant
size"default" | "sm" | "lg""default"The size of the toggle
defaultPressedbooleanfalseThe initial pressed state (uncontrolled)
pressedboolean-The controlled pressed state
onPressedChange(pressed: boolean) => void-Callback when pressed state changes
disabledbooleanfalseWhether the toggle is disabled

TypeScript

import type { ToggleVariants } from "@/components/ui/toggle";

type ToggleVariants = {
  variant?: "default" | "outline";
  size?: "default" | "sm" | "lg";
};

Examples

Default

The default toggle with transparent background:
import { Heart } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleDemo() {
  return (
    <Toggle aria-label="Toggle like">
      <Heart className="size-4" />
    </Toggle>
  );
}

Outline

Toggle with a border and subtle shadow:
import { Bold } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleOutline() {
  return (
    <Toggle variant="outline" aria-label="Toggle bold">
      <Bold className="size-4" />
    </Toggle>
  );
}

With Text

Combine icons with text labels:
import { Italic } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleWithText() {
  return (
    <Toggle variant="outline" aria-label="Toggle italic">
      <Italic className="size-4" />
      Italic
    </Toggle>
  );
}

Sizes

The toggle component comes in three sizes:
import { Bold } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleSmall() {
  return (
    <Toggle size="sm" variant="outline">
      <Bold className="size-4" />
    </Toggle>
  );
}

Disabled

Disable user interaction:
import { Underline } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleDisabled() {
  return (
    <Toggle variant="outline" disabled aria-label="Toggle underline">
      <Underline className="size-4" />
    </Toggle>
  );
}

Controlled

Control the toggle state with React state:
import { useState } from "react";
import { Bold } from "lucide-react";
import { Toggle } from "@/components/ui/toggle";

export default function ToggleControlled() {
  const [pressed, setPressed] = useState(false);

  return (
    <div className="flex flex-col gap-2">
      <Toggle
        variant="outline"
        pressed={pressed}
        onPressedChange={setPressed}
        aria-label="Toggle bold"
      >
        <Bold className="size-4" />
      </Toggle>
      <p className="text-sm text-muted-foreground">
        Bold is {pressed ? "on" : "off"}
      </p>
    </div>
  );
}

Variants

Default

Transparent background with hover and pressed states:
<Toggle>Toggle me</Toggle>

Outline

Bordered variant with background on hover:
<Toggle variant="outline">Toggle me</Toggle>

Accessibility

  • Uses the button role with aria-pressed attribute
  • Supports keyboard navigation (Space and Enter keys)
  • Clearly indicates pressed state to screen readers
  • Always include an aria-label for icon-only toggles

Base UI Reference

For more information about the underlying Base UI Toggle component, see the Base UI documentation.

Build docs developers (and LLMs) love