# Toggle

Toggle a button between pressed and unpressed states.

Bookmark toggle

[Complete TSX file](/examples/toggle/default.tsx)

```tsx
"use client";

import { BookmarkIcon } from "lucide-react";
import { Toggle } from "@/siteplane/components/toggle";

export default function Example() {
  return (
    <Toggle variant="outline">
      <BookmarkIcon />
      Bookmark
    </Toggle>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/toggle
```

With npm: `npx shadcn@4.18.0 add @siteplane/toggle`. [Registry JSON](/registry/toggle.json) lists source files and dependencies.

## Usage

```tsx
import { Toggle } from "@/siteplane/components/toggle";

<Toggle variant="outline">Bookmark</Toggle>;
```

## Variants and disabled state

The default variant has no border until it is hovered or pressed; `outline` adds one. Disabled toggles keep their pressed appearance.

Default, outline and disabled toggles

[Complete TSX file](/examples/toggle/variants.tsx)

```tsx
"use client";

import {
  BoldIcon,
  ItalicIcon,
  StrikethroughIcon,
  UnderlineIcon,
} from "lucide-react";
import { Toggle } from "@/siteplane/components/toggle";

export default function Example() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Toggle>
        <ItalicIcon />
        Italic
      </Toggle>
      <Toggle variant="outline">
        <BoldIcon />
        Bold
      </Toggle>
      <Toggle disabled>
        <UnderlineIcon />
        Underline
      </Toggle>
      <Toggle defaultPressed disabled variant="outline">
        <StrikethroughIcon />
        Strikethrough
      </Toggle>
    </div>
  );
}
```

## Icon-only toggles

Use `padding="icon"` for square icon-only toggles and give each one an `aria-label` that stays the same when it is pressed.

Formatting toggles with icons

[Complete TSX file](/examples/toggle/padding.tsx)

```tsx
"use client";

import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
import { Toggle } from "@/siteplane/components/toggle";

export default function Example() {
  return (
    <div className="flex items-center gap-1">
      <Toggle aria-label="Bold" padding="icon" variant="outline">
        <BoldIcon />
      </Toggle>
      <Toggle aria-label="Italic" padding="icon" variant="outline">
        <ItalicIcon />
      </Toggle>
      <Toggle aria-label="Underline" padding="icon" variant="outline">
        <UnderlineIcon />
      </Toggle>
    </div>
  );
}
```

## Sizes

Omit `size` to inherit the provider’s control size.

Toggle sizes

[Complete TSX file](/examples/toggle/sizes.tsx)

```tsx
"use client";

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

const sizes = [
  ["sm", "Small"],
  ["md", "Medium"],
  ["lg", "Large"],
  ["xl", "Extra large"],
] as const;

export default function Example() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      {sizes.map(([size, label]) => (
        <Toggle key={size} size={size} variant="outline">
          {label}
        </Toggle>
      ))}
    </div>
  );
}
```

## Controlled state

Pass `pressed` and `onPressedChange` when your application owns the state, for example an editor’s current formatting.

Controlled italic toggle

[Complete TSX file](/examples/toggle/controlled.tsx)

```tsx
"use client";

import { ItalicIcon } from "lucide-react";
import { useState } from "react";
import { Toggle } from "@/siteplane/components/toggle";

export default function Example() {
  const [pressed, setPressed] = useState(false);
  return (
    <Toggle onPressedChange={setPressed} pressed={pressed} variant="outline">
      <ItalicIcon />
      Italic
    </Toggle>
  );
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| variant | default \| outline | default | Surface. |
| size | sm \| md \| lg \| xl | provider / lg | Control size. |
| padding | default \| comfortable \| icon | default | Padding or square layout. |
| pressed / defaultPressed | boolean | unset / false | Controlled or initial state. |
| onPressedChange | (pressed, eventDetails) => void | unset | State callback. |
| disabled | boolean | false | Prevents interaction. |
| lift | boolean | false | Lifts the icon once each time the toggle turns on, for a reaction such as a like. The icon is the first child; reduced motion keeps it still. |

`TogglePrimitive` exports Base UI Toggle. `toggleVariants({size, variant, padding, className})` returns the utility classes Toggle adds beside its stylesheet, with `lg` size and `default` variant; the look comes from the kit stylesheet through the attributes Toggle renders. The component also defaults padding to default. Other props and refs follow [Base UI Toggle](https://base-ui.com/react/components/toggle).

[Read the installed source](/source/toggle).

## Usage notes

Space or Enter toggles the button. Keep the label and icon the same in both states; the pressed state is announced separately. Toggle does not submit a boolean form value; use Checkbox/Switch or serialize application state.
