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

import { Toggle } from '@/components/ui/toggle'

export default function ToggleDemo() {
  return (
    <Toggle aria-label="Toggle bold">
      <BoldIcon />
    </Toggle>
  )
}

function BoldIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8" />
    </svg>
  )
}

Built on Base UI

Installation

pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/toggle.json

Needs a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.

Toggle imports cn() from lib/utils.ts — add it too if you don't have it yet:

import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Usage

import { Toggle } from '@/components/ui/toggle'

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

<Toggle variant="outline" size="sm" defaultPressed>
  Italic
</Toggle>

Examples

Variants

import { Toggle } from '@/components/ui/toggle'

export default function ToggleVariants() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Toggle aria-label="Toggle italic">
        <ItalicIcon />
        Italic
      </Toggle>
      <Toggle variant="outline" aria-label="Toggle italic, outlined">
        <ItalicIcon />
        Italic
      </Toggle>
      <Toggle variant="outline" defaultPressed aria-label="Toggle italic, outlined, on by default">
        <ItalicIcon />
        On
      </Toggle>
      <Toggle variant="outline" disabled aria-label="Toggle italic, disabled">
        <ItalicIcon />
        Disabled
      </Toggle>
    </div>
  )
}

function ItalicIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M19 4h-9M14 20H5M15 4 9 20" />
    </svg>
  )
}

Sizes

import { Toggle } from '@/components/ui/toggle'

export default function ToggleSizes() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Toggle variant="outline" size="sm" aria-label="Toggle underline, small">
        <UnderlineIcon />
      </Toggle>
      <Toggle variant="outline" aria-label="Toggle underline, default size">
        <UnderlineIcon />
      </Toggle>
      <Toggle variant="outline" size="lg" aria-label="Toggle underline, large">
        <UnderlineIcon />
      </Toggle>
    </div>
  )
}

function UnderlineIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M6 4v6a6 6 0 0 0 12 0V4M4 20h16" />
    </svg>
  )
}

API Reference

NameTypeDefaultDescription
variant'default' | 'outline''default'Visual style. Outline adds a border.
size'sm' | 'default' | 'lg''default'Height and padding.
pressed / onPressedChangeboolean / (pressed: boolean) => void—Controlled pressed state.
defaultPressedbooleanfalseInitial pressed state (uncontrolled).
disabledbooleanfalseIgnores user interaction.
toggleVariants(options) => string—Exported helper that returns the toggle classes, for styling another element to match.