Folio

Components

Toggle

A two-state button that can be either on or off. Use it for a single formatting control -- bold, italic, mute -- where the pressed state holds until the user toggles it back.

Preview

Rendered with live Folio tokens -- hover and the pressed state (an accent surface with primary text) remap on theme change, no dark: classes. Click a control to toggle it.

Variants

<Toggle aria-label="Toggle bold">
  <Bold />
</Toggle>
<Toggle variant="outline" aria-label="Toggle italic">
  <Italic />
</Toggle>
<Toggle aria-label="Toggle bold">
  <Bold />
  Bold
</Toggle>
<Toggle size="sm" aria-label="Bold"><Bold /></Toggle>
<Toggle size="default" aria-label="Bold"><Bold /></Toggle>
<Toggle className="h-10 min-w-10 px-2.5" aria-label="Bold">
  <Bold />
</Toggle>

default is borderless for toolbars; outline adds a border when it stands alone. Pair an icon with a label for clarity, and use size for sm / default. There is no lg size; set the height with className when you need one.

States

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

Off is transparent; on fills with the accent surface and primary text (data-[state=on]); a disabled toggle dims to 50% and stops responding.

API

Prop
Type
Default
Description
pressed
boolean
undefined
Controlled on/off state. Pair with onPressedChange.
defaultPressed
boolean
false
Initial state when uncontrolled.
onPressedChange
(pressed: boolean) => void
undefined
Fires when the user toggles it.
variant
"default" | "outline" | "secondary"
"default"
default is borderless; outline adds a border for standalone use; secondary is a segment inside a secondary ToggleGroup track.
size
"default" | "sm" | "xs" | "xxs" | "icon" | "icon-sm" | "icon-xs" | "icon-xxs"
"default"
Control height and padding (h-9 / h-8 / h-7 / h-6). Icon sizes are square.
tooltipText
string
undefined
Wraps the toggle in a Tooltip that shows on hover.
disabled
boolean
false
Dims to 50% and blocks interaction.

Don't and Do

Don't

Don't use a Toggle for a setting that needs an explicit on/off label -- that's a Switch. And don't group mutually exclusive options with separate Toggles; reach for a toggle group or Tabs so only one stays pressed.

Do
<Toggle aria-label="Toggle bold">
  <Bold />
</Toggle>
import { Toggle } from "@/components/shadcn/toggle";
import { Bold } from "lucide-react";

export function BoldToggle() {
  const [pressed, setPressed] = useState(false);
  return (
    <Toggle
      pressed={pressed}
      onPressedChange={setPressed}
      aria-label="Toggle bold"
    >
      <Bold />
    </Toggle>
  );
}
API matches @distylai/toolkit-ui -- Toggle and toggleVariants on Radix. The raw muted / accent / ring / primary-50 colors are replaced with Folio tokens.