<!-- Protocore Design System — Burger -->
# Burger

- **Category:** Utilities (`utilities`)
- **Slug:** `utilities/burger`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Burger } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/utilities/burger

> An animated hamburger↔close toggle — the mobile-nav trigger, reflecting its open state via aria-expanded.

## When to use it

**Burger** is the mobile-navigation trigger: a compact button that toggles a menu and animates to reflect whether that menu is open. It is purely a *trigger* — it owns no menu of its own. Wire `opened`/`onToggle` to the same state that drives your [Sheet](/overlay/sheet) or [Sidebar](/navigation/sidebar), so the icon and the drawer never disagree.

Keep it to genuinely responsive navigation. On wide layouts where the nav is always visible, don't show a Burger — there is nothing to reveal.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `aria-label` | `string` | no | `Open navigation` | Accessible name for the control — required, since the icon carries no text. |
| `className` | `string` | no | — | — |
| `onToggle` | `((opened: boolean) => void)` | no | — | Called with the next opened state when the button is activated. |
| `opened` | `boolean` | no | `false` | Whether the burger is in its open (X) state. Controlled. |
| `size` | `enum` | no | `md` | Square control size: `sm` 32 · `md` 36 · `lg` 40. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

A controlled toggle: hold the `opened` state yourself and update it from `onToggle`. The three lines morph into an X when opened; reduced-motion snaps between the two.

```tsx
import { useState } from "react";
import { Burger } from "@protocore/pds";

export default function Basics() {
  const [opened, setOpened] = useState(false);
  return (
    <Burger
      opened={opened}
      onToggle={setOpened}
      aria-label={opened ? "Close navigation" : "Open navigation"}
    />
  );
}
```

### Driving a navigation drawer

The canonical use — a Burger that opens a [Sheet](/overlay/sheet) of navigation on small screens. Its `aria-expanded` tracks the drawer, and its label flips between "Open" and "Close navigation".

```tsx
import { useState } from "react";
import { Burger, Sheet, Stack, Link } from "@protocore/pds";

export default function Drawer() {
  const [opened, setOpened] = useState(false);
  return (
    <Sheet.Root open={opened} onOpenChange={setOpened}>
      <Sheet.Trigger asChild>
        <Burger opened={opened} aria-label={opened ? "Close navigation" : "Open navigation"} />
      </Sheet.Trigger>
      <Sheet.Content size="sm">
        <Sheet.Title>Navigation</Sheet.Title>
        <Stack gap={3} style={{ marginTop: 16 }}>
          <Link href="#validators">Validators</Link>
          <Link href="#epochs">Epochs</Link>
          <Link href="#treasury">Treasury</Link>
          <Link href="#settings">Settings</Link>
        </Stack>
      </Sheet.Content>
    </Sheet.Root>
  );
}
```

## Do & don't

**Do**

- Bind `opened` to the same state as the drawer it controls.
- Update the `aria-label` to describe the *next* action ("Open" vs "Close navigation").
- Match its `size` to the other controls in the bar.
- Show it only at breakpoints where the navigation is collapsed.

**Don't**

- Don't leave `aria-label` at a generic value that ignores the current state.
- Don't animate it out of sync with the menu it toggles.
- Don't use it as a generic icon button — it means "toggle navigation".
- Don't show it when the full navigation is already on screen.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Moves focus to the toggle. |
| `Enter / Space` | Toggles it, firing onToggle with the next state. |

**Notes**

- Renders a real `<button>` exposing `aria-expanded` bound to `opened`, so assistive tech announces the collapsed/expanded state.
- Requires an accessible name via `aria-label` (default "Open navigation") — the animated lines are `aria-hidden`.
- The morph is pure CSS transform; `prefers-reduced-motion` snaps between hamburger and X with no tween.
- The lines are `<span>` elements, not a text glyph, so nothing renders as an emoji.

## Related

`close-button`, `sheet`, `sidebar`, `app-shell`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
