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

- **Category:** Layout (`layout`)
- **Slug:** `layout/top-bar`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { TopBar, TopBarLinkItem } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/layout/top-bar

> A sticky, blurred top navigation bar with brand, mono uppercase links, and an actions cluster.

## When to use it

`TopBar` is the generic top chrome — a site or product header with a brand, a short run of primary destinations, and a right-side action cluster. It is deliberately *not* any one site's header; skin it per surface. Use it for top-level, marketing, or shallow navigation; use `Sidebar` when an application has many grouped destinations that warrant a persistent rail. The two pair inside `AppShell` (bar on top, rail on the left). For the `links` prop, each link is plain data; when you need `asChild` or richer content, switch to the `children` form with `TopBarLinkItem`. Wire a menu `IconButton` in `actions` to `AppShell`'s `onSidebarOpenChange` to toggle the mobile drawer.

## Props

### TopBar

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `actions` | `ReactNode` | no | — | Right-cluster actions (buttons, theme toggle…). |
| `brand` | `ReactNode` | no | — | Left-cluster brand mark / wordmark. |
| `children` | `ReactNode` | no | — | Custom nav content — replaces `links` entirely. |
| `className` | `string` | no | — | — |
| `links` | `TopBarLink[]` | no | — | Inline nav links, rendered between brand and actions. Ignored if `children` is set. |
| `sticky` | `boolean` | no | `true` | Pin to the top of the scroll container. Default true. |
| `style` | `CSSProperties` | no | — | — |

### TopBar.Link

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `active` | `boolean` | no | — | Mark the current section — renders in ink. |
| `asChild` | `boolean` | no | — | Render into a passed child (e.g. a router `<Link>`) instead of an `<a>`. |
| `className` | `string` | no | — | — |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

Pass a `brand`, a `links` array, and an `actions` slot. Links render as mono uppercase; the `active` one inks. The bar is blurred, hairline-bottomed, and sticky by default (disabled here for the demo).

```tsx
import { TopBar, Logo, Button } from "@protocore/pds";

export default function TopBarBasics() {
  return (
    <TopBar
      sticky={false}
      brand={<Logo label="PROTOCORE" size="sm" />}
      links={[
        { label: "Products", href: "#", active: true },
        { label: "Docs", href: "#" },
        { label: "Pricing", href: "#" },
        { label: "Status", href: "#" },
      ]}
      actions={
        <Button variant="secondary" size="sm">
          Console
        </Button>
      }
    />
  );
}
```

### Custom nav with TopBarLinkItem

For links that need `asChild` (to wrap a router `<Link>`) or custom markup, pass `children` instead of `links` and compose `TopBarLinkItem`s yourself. `children` replaces `links` entirely.

```tsx
import { TopBar, TopBarLinkItem, Logo, IconButton } from "@protocore/pds";
import { Menu } from "lucide-react";

export default function TopBarCustomNav() {
  return (
    <TopBar
      sticky={false}
      brand={<Logo label="PROTOCORE" size="sm" />}
      actions={
        <IconButton aria-label="Open menu" variant="ghost" size="sm">
          <Menu size={16} />
        </IconButton>
      }
    >
      <TopBarLinkItem href="#" active>
        Overview
      </TopBarLinkItem>
      <TopBarLinkItem href="#">Nodes</TopBarLinkItem>
      <TopBarLinkItem href="#">Ledger</TopBarLinkItem>
    </TopBar>
  );
}
```

## Do & don't

**Do**

- Keep the link run short — a handful of top-level destinations.
- Use the children + TopBarLinkItem form when links must wrap a router Link via asChild.
- Put the primary call to action in the actions slot, not among the nav links.

**Don't**

- Cram deep, grouped navigation into a TopBar — that is a Sidebar.
- Pass both links and children; children wins and links is ignored.
- Disable sticky unless the bar genuinely shouldn't follow the scroll.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Move focus through the brand, links, and actions in order |
| `Shift + Tab` | Move focus backward through the bar |
| `Enter` | Follow the focused link or activate the focused action |

**Notes**

- Renders a `<header>` with a `<nav>` around the links — an implicit navigation landmark.
- The active link sets `aria-current="page"`.
- Links opening in a new tab (`target="_blank"`) default to `rel="noreferrer"`.
- Icon-only actions (e.g. a menu button) must carry an `aria-label`.

## Related

`sidebar`, `app-shell`, `footer`, `env-strip`

---

© 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/
