Skip to main content

TopBar

Organismbeta@macaw-ds/ui · since 0.1.0

The application's global header: brand, optional centre content and actions. Not a page title; that is PageHeader.

Import

import { TopBar } from '@macaw-ds/ui';

Props

PropTypeDefaultDescription
brand*ReactNode—

Product mark and name, usually a link to home.

childrenReactNode—

Centre content such as a search field or an environment switcher.

actionsReactNode—

Right-aligned actions: help, notifications, theme toggle, account. Use ghost icon-only Buttons.

Slots

Named parts you pass content into.

  • brand
  • children
  • actions

Tokens used

Every value this component renders comes from one of these tokens.

TokenLightDark
size.topbar

semantic · dimension

56px
56px
color.surface.layer-1

semantic · color

oklch(1 0 0)
oklch(0.15 0.012 250)
color.line.default

semantic · color

oklch(0.925 0.005 250)
oklch(0.29 0.012 250)
z.sticky

primitive · number

100
100

Eject

Ejecting copies the source into your repo and records it in .macaw/ejected.json, so the fork stays visible. The same file is served as a shadcn-compatible registry item.

With the MACAW CLI
npx @macaw-ds/cli add top-bar --eject
With shadcn
npx shadcn@latest add https://macaw-design-system.vercel.app/r/top-bar.json

Bundle budget: 1,000 bytes gzipped, enforced by size-limit in CI.

Manifest

registry/manifests/top-bar.json, the contract the playground, CLI, plugin and MCP server read.

{
  "name": "TopBar",
  "slug": "top-bar",
  "package": "@macaw-ds/ui",
  "status": "beta",
  "since": "0.1.0",
  "level": "organism",
  "category": "layout",
  "purpose": "The application's global header: brand, optional centre content and actions. Not a page title; that is PageHeader.",
  "description": "A sticky banner landmark on surface layer-1 with a bottom border. Its height is size.topbar (56px comfortable, 48px compact), which sticky elements below it use as their offset. Content is passed through three slots.",
  "exports": [
    "TopBar"
  ],
  "props": {
    "brand": {
      "type": "node",
      "required": true,
      "description": "Product mark and name, usually a link to home.",
      "control": "none"
    },
    "children": {
      "type": "node",
      "required": false,
      "description": "Centre content such as a search field or an environment switcher.",
      "control": "none"
    },
    "actions": {
      "type": "node",
      "required": false,
      "description": "Right-aligned actions: help, notifications, theme toggle, account. Use ghost icon-only Buttons.",
      "control": "none"
    }
  },
  "slots": [
    "brand",
    "children",
    "actions"
  ],
  "tokens": [
    "size.topbar",
    "color.surface.layer-1",
    "color.line.default",
    "z.sticky"
  ],
  "a11y": {
    "role": "banner (header element at the top level)",
    "focusable": false,
    "keyboard": [],
    "name": "Not named; there is one banner per page.",
    "notes": [
      "The TopBar is not focusable itself; its brand link and action buttons are.",
      "Sticky content below it offsets by top-topbar so it is never obscured (WCAG 2.2 SC 2.4.11).",
      "Sticky only at 1024px and wider; below that it scrolls away so a zoomed or narrow viewport keeps its height for content."
    ]
  },
  "budget": {
    "gzip": 1000
  },
  "rules": [
    "One TopBar per page, placed in AppShell's topBar slot.",
    "Actions are ghost Buttons; icon-only actions need aria-label.",
    "Never put the page title in the TopBar; that belongs to PageHeader."
  ],
  "dos": [
    "Link the brand to the product home."
  ],
  "donts": [
    "Do not add a primary Button to the TopBar; primary actions belong to the page."
  ],
  "examples": [
    {
      "name": "Default",
      "props": {}
    }
  ],
  "registryDependencies": [],
  "dependencies": [],
  "related": [
    "app-shell",
    "side-nav",
    "page-header"
  ]
}