# Navbar

> The bar across the top of a site: brand, links, and actions, with a menu on narrow screens.

- Name: `navbar`
- Status: beta
- Categories: navigation, header, marketing
- Files: the install writes `navbar.tsx`, and any part files named `navbar-*.tsx`, to your `components` alias, `@/components` by default. Edit them freely. They are yours.
- Other registry items: `@arbokui/button`, `@arbokui/popover`. The install adds them.
- Gallery: https://arbokui.com/website/navbar
- Registry item: https://arbokui.com/r/navbar.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the website component. It also adds every component it uses:

   ```bash
   npx shadcn@latest add @arbokui/navbar
   ```

## Use it for

- The top of a marketing site, docs site, or app, with up to six main links.
- Group related pages into a menu, with \`items\`, like Product or Who it's for. Give its items a short \`description\` when the names alone don't say enough.
- Mark the page you are on with \`current: true\`, so it gets a soft fill and aria-current.
- Pass your router's link through \`renderLink\`, like next/link, so links stay client-side.
- Put a sign-in and a main call to action in \`actions\`. On narrow screens they move into the menu.
- Set \`collapseBelow\` to the smallest width your links and actions fit in. More links need a bigger one.
- Set \`floating\` on a landing page, so the bar stays in reach as a pill while people scroll.

## Avoid it for

- More than six entries in the bar. Group the rest into a menu, or move them into the footer.
- A menu with one item, or more than about eight. Link straight to the one page, or split the list.
- A menu inside a menu. On narrow screens each menu is a heading with its links under it, one level deep.
- Links inside an app's own screens, like settings sections. Use Tabs, or a sidebar.
- A trail of where you are. Use Breadcrumb.

## Props

- `brand`: `ReactNode`. Your logo or name. It links to brandHref.
- `brandHref`: `string`. Default `"/"`. Where the brand links.
- `links`: `({ href: string; label: string; current?: boolean } | NavbarMenu)[]`. The main links, in order. Each href must be unique, since it is the key. A menu, with \`items\`, opens a list of links instead.
- `NavbarMenu`: `{ label: string; items: { href: string; label: string; description?: ReactNode; icon?: ReactNode; current?: boolean }[] }`. Type. A menu in the bar. It opens on hover after a short pause, or on a click or Enter. Items with a description show it under the label, two columns from four items. An icon needs a description. Labels must be unique.
- `actions`: `ReactNode`. Buttons on the right, like Sign in and Create a team. On narrow screens they sit at the bottom of the menu.
- `renderLink`: `(props: NavbarLinkProps) => ReactNode`. Default `a plain <a>`. Draws the brand and each link. Spread the props onto your router's link: (props) => \<Link {...props} />.
- `label`: `string`. Default `"Main"`. The name screen readers give the nav.
- `menuLabel`: `string`. Default `"Menu"`. The name of the menu button on narrow screens.
- `collapseBelow`: `"sm" | "md" | "lg" | "xl"`. Default `"lg"`. The navbar's own width below which links fold into the menu: 36, 42, 48, or 56rem. Pick the smallest your links and actions fit in.
- `floating`: `boolean`. Default `false`. Pins the navbar to the top. Once the page scrolls, the bar lifts into a rounded pill with a shadow, and the menu opens as a rounded panel.
- `className`: `string`. Extra classes on the header, which holds the container query. Add sticky top-0 z-40 here to pin it without the pill.

## Accessibility

- The links sit in a nav landmark named by \`label\`. Only one copy of the links is on screen at a time, so screen readers hear one nav.
- The current link has aria-current="page".
- On narrow screens a menu button opens the links. It says whether it is open with aria-expanded.
- Escape closes the menu and puts focus back on its button. A press outside the bar closes it too.
- Links in the menu are at least 44px tall for touch.
- On narrow screens \`actions\` render a second time, inside the menu. Do not give them an id.
- A menu's trigger is a button with aria-expanded. Its list opens as a non-modal popup named by the menu's label, so Tab moves on past it and closes it.
- Escape closes a menu and puts focus back on its trigger. Picking an item closes it too.
- The trigger also opens on hover, but never only on hover: a click, Enter, or Space opens it as well.
- In the narrow menu each menu's links sit in a list named by its heading, so nothing nests.

## Examples

### A marketing site

```tsx
<Navbar
  brand={<span className="font-semibold">Workspace</span>}
  links={[
    { href: "/features", label: "Features" },
    { href: "/pricing", label: "Pricing", current: true },
    { href: "/docs", label: "Docs" },
  ]}
  actions={
    <>
      <Button emphasis="ghost" size="sm">Sign in</Button>
      <Button tone="brand" size="sm">Create a team</Button>
    </>
  }
/>
```

### A floating pill on a landing page

```tsx
<Navbar
  floating
  brand="Workspace"
  links={[{ href: "/features", label: "Features" }, { href: "/pricing", label: "Pricing" }]}
  actions={<Button tone="brand" emphasis="outline" size="sm">Request access</Button>}
/>
```

### With menus

```tsx
<Navbar
  brand="Workspace"
  links={[
    {
      label: "Product",
      items: [
        { href: "/plan", label: "Planning", description: "Set up the week, with who is coming." },
        { href: "/agendas", label: "Agendas", description: "Run saved agendas and track goals." },
      ],
    },
    { href: "/pricing", label: "Pricing" },
    { label: "More", items: [{ href: "/blog", label: "Blog" }, { href: "/about", label: "About" }] },
  ]}
/>
```

### With next/link, pinned to the top

```tsx
<Navbar
  className="sticky top-0 z-40 border-b"
  brand="Workspace"
  links={[{ href: "/", label: "Home", current: true }, { href: "/blog", label: "Blog" }]}
  renderLink={(props) => <Link {...props} />}
/>
```
