# Toggle

Displays a boolean value.

---

## Default

```tsx
import { Toggle } from '@vercel/geistcn/components';
import { useState, type JSX } from 'react';

export function Component(): JSX.Element {
  const [checked, setChecked] = useState(false);
  const [checked2, setChecked2] = useState(true);

  return (
    <div className="flex relative min-w-px max-w-full flex-col flex-1">
      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked}
          onChange={(): void => setChecked(!checked)}
        />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked2}
          onChange={(): void => setChecked2(!checked2)}
        />
      </div>
    </div>
  );
}
```

## Disabled

```tsx
import { Toggle } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  return (
    <div className="flex relative min-w-px max-w-full flex-col flex-1">
      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle aria-label="Enable Firewall" checked={false} disabled />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle aria-label="Enable Firewall" checked disabled />
      </div>
    </div>
  );
}
```

## Sizes

```tsx
import { Toggle } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  return (
    <div className="flex relative min-w-px max-w-full flex-row flex-wrap flex-1">
      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle aria-label="Enable Firewall" checked={false} />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle aria-label="Enable Firewall" checked={false} size="large" />
      </div>
    </div>
  );
}
```

## Custom Color

```tsx
import { Toggle } from '@vercel/geistcn/components';
import { LockClosedSmall, LockOpenSmall } from '@vercel/geistcn/icons';
import { useState, type JSX } from 'react';

export function Component(): JSX.Element {
  const [checked, setChecked] = useState(false);

  return (
    <div className="flex relative min-w-px max-w-full flex-col flex-1">
      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked}
          color="amber"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
        />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked}
          color="red"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
        />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked}
          color="amber"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
          size="large"
        />
      </div>

      <div className="flex relative min-w-px max-w-full flex-col flex-1">
        <Toggle
          aria-label="Enable Firewall"
          checked={checked}
          color="red"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
          size="large"
        />
      </div>
    </div>
  );
}
```

## With Label

```tsx
import { Toggle } from '@vercel/geistcn/components';
import { LockClosedSmall, LockOpenSmall } from '@vercel/geistcn/icons';
import { useState, type JSX } from 'react';

export function Component(): JSX.Element {
  const [checked, setChecked] = useState(false);

  return (
    <div className="flex flex-col items-start justify-start gap-4 flex-initial">
      <div className="flex flex-row items-stretch justify-start gap-4 flex-initial">
        <Toggle checked={checked} onChange={(): void => setChecked(!checked)}>
          Enable Firewall
        </Toggle>
        <Toggle
          checked={checked}
          direction="switch-first"
          onChange={(): void => setChecked(!checked)}
        >
          Enable Firewall
        </Toggle>
      </div>
      <div className="flex flex-row items-stretch justify-start gap-4 flex-initial">
        <Toggle
          checked={checked}
          onChange={(): void => setChecked(!checked)}
          size="large"
        >
          Enable Firewall
        </Toggle>
        <Toggle
          checked={checked}
          direction="switch-first"
          onChange={(): void => setChecked(!checked)}
          size="large"
        >
          Enable Firewall
        </Toggle>
      </div>
      <div className="flex flex-row items-stretch justify-start gap-4 flex-initial">
        <Toggle
          checked={checked}
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
        >
          Enable Firewall
        </Toggle>
        <Toggle
          checked={checked}
          direction="switch-first"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
        >
          Enable Firewall
        </Toggle>
      </div>
      <div className="flex flex-row items-stretch justify-start gap-4 flex-initial">
        <Toggle
          checked={checked}
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
          size="large"
        >
          Enable Firewall
        </Toggle>
        <Toggle
          checked={checked}
          direction="switch-first"
          icon={{
            checked: <LockClosedSmall />,
            unchecked: <LockOpenSmall />,
          }}
          onChange={(): void => setChecked(!checked)}
          size="large"
        >
          Enable Firewall
        </Toggle>
      </div>
    </div>
  );
}
```

## Best Practices

* Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`. Switch to `Checkbox` for a multi-select list, or to `Switch` for 2–3 mutually exclusive views.
* `checked` is required and the component is controlled. Own the state and update it from `onChange`.
* Persist on change and surface the result in a `useToasts().success(…)` toast (`Password protection enabled`); don’t leave the user wondering whether the flip stuck. Pair with a form footer only when the setting needs an explicit `Save` step.
* Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver.
* The label is `children`, not a `label` prop. Title Case noun phrase, 1–4 words, naming what is true when ON: `Password Protection`, not `Enable Password Protection`.
* Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation.
* Keep `labelCasing="title"` (the default) so labels match other Title Case surfaces. Use `labelCasing="normal"` only when sentence-case content sits inline next to the toggle.
* Provide an accessible name through `children`, `aria-label`, or `aria-labelledby`. Geist warns in development if all three are missing.
* Set `aria-label` only when the visible label sits elsewhere on the row; otherwise let `children` carry it so sighted and screen-reader copy stay aligned.
