# Navbar

> A responsive site header that collapses its links into a mobile panel below the md breakpoint.

URL: https://apogee.avaui.dev/docs/navbar
Last updated: 2026-10-16

A responsive site header that collapses its links into a mobile panel below the md breakpoint.

Last updated October 16, 2026

Uses JavaScript

Wires the mobile menu toggle: clicking it flips `data-open` on the collapsible links panel and syncs `aria-expanded`.

**Without JS:** The toggle is hidden (\`no-js:hidden\`) and the links panel stays expanded (\`no-js:flex\`), so below the md breakpoint the nav is fully reachable without a working control to click. Desktop viewports (md and up) are unaffected: links show inline via CSS regardless of JS.

```astro
<Navbar>
<a slot="brand" href="/" class="text-lg font-semibold">Larkspur</a>
<NavLink href="/docs">Docs</NavLink>
<NavLink href="/pricing">Pricing</NavLink>
</Navbar>
```

`floating` sets the bar on a rounded, raised pill:

```astro
<Navbar floating>…</Navbar>
```

`background` sets the bar’s fill. `page` (the default) is the page colour, slightly see-through over what scrolls under it. `neutral-faded` is a grey band. `primary` is the brand colour: links, the menu button and the buttons in `actions` switch to the on-brand colours on their own, and dropdown panels keep the page colours.

```astro
<Navbar background="primary">…</Navbar>
```

For a dark bar on a light page, give it `data-theme="dark"`.

## Add

```sh
npx @ava-ui/apogee add navbar
```

No Apogee dependencies (compose the link slot with `NavLink` for free active-state styling). Bring `@lucide/astro` for the mobile menu icon. Ships one scoped JS island (progressive enhancement).

## Usage

```astro
---
import Navbar from '@/components/apogee/Navbar/Navbar.astro'
import NavLink from '@/components/apogee/NavLink/NavLink.astro'
---
<Navbar>
  <a slot="brand" href="/">Larkspur</a>
  <NavLink href="/docs">Docs</NavLink>
  <NavLink href="/pricing">Pricing</NavLink>
</Navbar>
```

## Anatomy

-   **`brand` slot** — logo or wordmark, leftmost.
-   **default slot** — nav links. Inline row on desktop (md and up); a stacked panel below the header on mobile, hidden until the toggle opens it.
-   **`actions` slot** — end-aligned buttons/controls. Rendered inline on desktop and again at the bottom of the mobile panel, so they stay reachable at every width. Don’t put elements with ids in it; they would be duplicated.
-   **`tools` slot** — icon buttons that stay in the bar at every width (a theme switch, a repository link), just before the menu toggle on phones. Rendered once, so ids are fine here.
-   **`secondary` slot** — a second row under the header, full width, for the active section’s tabs or pills. Scrolls sideways when it overflows.
-   **mobile toggle** — a hamburger button (`md:hidden`), controls the links panel via `aria-controls` / `aria-expanded`.

## API

`@composable` — exposed to Content Editors in AVA. Any other attribute passes through to the root `<header>` (`...rest`).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `floating` | `boolean` | `false` | The bar on a rounded, raised pill with space around it. |
| `background` | `'page' \| 'neutral-faded' \| 'primary'` | `'page'` | The bar’s fill. `primary` is the brand colour; everything in the bar takes the on-brand colours. |
| `centered` | `boolean` | `false` | Links in the middle, brand and actions at the edges. |
| `menuLabel` | `string` | `'Toggle menu'` | Name of the phone menu button. |
| `secondaryLabel` | `string` | `'Section'` | Name of the `secondary` nav row. |
| `class` | `string` | — | Extra classes on the root `<header>`, merged last. |

## States

-   **Collapsed** (mobile, default) — the links panel is hidden below the md breakpoint until toggled open.
-   **Open** (mobile) — `data-open="true"` on the panel; toggle’s `aria-expanded="true"`.
-   **Desktop** (md and up) — links show inline always; the toggle and its panel logic don’t apply.
-   **No JS** — see the JsNote above; the toggle is hidden and the links panel stays expanded.

## Examples

With brand, links, and actions:

```astro
<Navbar>
<a slot="brand" href="/" class="text-lg font-semibold">Larkspur</a>
<NavLink href="/docs">Docs</NavLink>
<NavLink href="/pricing">Pricing</NavLink>
<NavLink href="/blog">Blog</NavLink>
<Button slot="actions" variant="ghost" color="neutral" href="/login">Log in</Button>
<Button slot="actions" href="/signup">Sign up</Button>
</Navbar>
```

Icon buttons in `tools` stay in the bar on phones, next to the menu toggle:

```astro
<Navbar>
<a slot="brand" href="/">Larkspur</a>
<NavLink href="/docs">Docs</NavLink>
<NavLink href="/pricing">Pricing</NavLink>
<Button slot="actions" href="/signup">Sign up</Button>
<Tooltip slot="tools" text="Dark theme" placement="bottom">
  <Button variant="ghost" color="neutral" iconOnly aria-label="Dark theme"><Moon /></Button>
</Tooltip>
</Navbar>
```

A second row for the active section, and a centred layout:

```astro
<Navbar>
<a slot="brand" href="/">Larkspur</a>
<NavLink href="/docs" match="prefix">Docs</NavLink>
<NavLink href="/pricing">Pricing</NavLink>
<Tabs slot="secondary" variant="underline" tabs={[{ label: 'Overview' }, { label: 'Members' }, { label: 'Billing' }]} />
</Navbar>
<Navbar centered>…</Navbar>
```

## Accessibility

| Key | Action |
| --- | --- |
| `Tab` | Moves through the links, actions and menu toggle in DOM order. |
| `Enter` `Space` | On the toggle, open / close the mobile menu. |
| `Enter` | On a link, follows it. |

-   `<header>` / `<nav>` landmarks wrap the content.
-   The toggle is a real `<button>` with `aria-controls` pointing at the panel’s id and `aria-expanded` synced by JS; `aria-label="Toggle menu"` since it’s icon-only.
-   **No JS** — the toggle carries `no-js:hidden` and the links panel carries `no-js:flex`, so on mobile the toggle disappears and the links render expanded — never a dead control, and the nav stays fully reachable. Desktop is unaffected — links and actions render inline via CSS regardless of JS.

## Tokens

| Token | Used for |
| --- | --- |
| `--border-neutral` | Header bottom border / mobile panel border |
| `--background-page` | Header and mobile panel background |
| `--foreground-neutral` | Toggle icon colour |
| `--background-neutral-faded-highlighted` | Toggle hover background |
| `--outline-color-focus` | Toggle focus ring |

## Do / Don’t

-   **Do** put the primary call-to-action in `actions`, not buried in the link list.
-   **Do** pair the default slot with `NavLink` so the current page gets its active state for free.
-   **Don’t** put elements with `id`s in the `actions` slot — it renders twice (inline on desktop, inside the mobile panel), so ids would collide.
-   **Don’t** assume the toggle is visible without JS — it’s `no-js:hidden` by design; the links panel takes over as the fallback instead.

## Content

-   Keep top-level link labels to one or two words; put anything longer in a dropdown or menu component instead.
-   Give the `brand` slot real link text, or an `aria-label` / `alt` if it’s a logo image only.

## Related

[

SidebarA vertical navigation aside, sticky and full-height on desktop, collapsible behind a toggle on mobile.

](https://apogee.avaui.dev/docs/sidebar)[

NavLinkA navigation link that auto-detects and styles the current route, with prefix matching, external links and a collapsible NavGroup.

](https://apogee.avaui.dev/docs/nav-link)[

FooterA site footer shell for link columns and a bottom copyright row.

](https://apogee.avaui.dev/docs/footer)
