Askr
UI & Components

Navbar and Navigation Menu

Use navbar and navigation menu with the current published Askr packages.

  • @askrjs/themes/navigation-menu0.0.13

How to use navbar and navigation menu

Navbar and Navigation Menu should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.

  1. Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
  2. Keep navbar and navigation menu labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
  3. Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink, NavigationMenuList } from '@askrjs/themes/components';

<NavigationMenu aria-label="Primary navigation">
  <NavigationMenuList>
    <NavigationMenuItem><NavigationMenuLink href={projectsRoute}>Projects</NavigationMenuLink></NavigationMenuItem>
    <NavigationMenuItem><NavigationMenuLink href={reportsRoute}>Reports</NavigationMenuLink></NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>

Purpose

Despite the page title, the only export at `@askrjs/themes/navigation-menu` is `NavigationMenu` and its parts — there's no separate `Navbar` primitive on this subpath. Use these pieces to build a horizontal menu bar with flyout content: a top-level list of items, each optionally opening a panel of links. If you actually want the responsive app-header component (with a collapsing hamburger state), that's `Navbar` from the general themes component barrel, not this one.

Install and import

```tsx import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuViewport, NavigationMenuIndicator, } from '@askrjs/themes/navigation-menu'; ``` This subpath is an alias into the shared components barrel, so importing the same names from `@askrjs/themes/components` works identically.

Live examples

Implement live examples at the navbar and navigation menu boundary: make inputs visible at the call site, keep cleanup with the work that created it, and render the success, unavailable, and failure states where a user can act on them.

Anatomy

`NavigationMenu` renders a `<nav>`, `NavigationMenuList` an `<ul>`, and `NavigationMenuItem` an `<li>` — a plain nested list under the hood. `NavigationMenuTrigger` is a real `<button type="button">` (with the `nav-item` class baked in), while `NavigationMenuContent`, `NavigationMenuLink`, `NavigationMenuViewport`, and `NavigationMenuIndicator` are generic slotted elements (a div, an anchor, a div, and a div respectively) that only exist to give you stable markup and `data-slot` hooks for the flyout panel, its links, the clipping viewport, and an active-tab indicator strip.

State model

None of these components track open/closed state, active item, or hover intent — there's no internal store or context here at all. You decide which trigger's content is visible, typically with a bit of local state or by composing `NavigationMenuTrigger`/`NavigationMenuContent` with the interaction primitives from `@askrjs/ui` (the same way the themed `Navbar` wires its own collapse menu with `Dropdown`/`DropdownTrigger`). Treat this package as markup, not behavior.

Keyboard and accessibility

Because `NavigationMenu` is a `<nav>` and `NavigationMenuTrigger` is a genuine `<button>`, you get landmark navigation and native Tab/Enter/Space activation for free. What you don't get automatically is `aria-expanded`, `aria-controls`, or Escape-to-close on the trigger/content pair, or arrow-key movement across items — those are your responsibility to wire up if you're building a real dropdown-style flyout rather than a flat link list.

Styling and tokens

Every part carries a `data-slot` attribute — `navigation-menu`, `navigation-menu-list`, `navigation-menu-item`, `navigation-menu-trigger`, `navigation-menu-content`, `navigation-menu-link`, `navigation-menu-viewport`, `navigation-menu-indicator` — and the trigger additionally gets the `nav-item` class. Style off those hooks instead of assuming a fixed DOM shape, since `as`/`asChild` let consumers swap the underlying element.

API

All parts accept the shared `CatalogComponentProps` shape: `as` to render a different tag, `asChild` to hand rendering off to a `Slot` (useful for wrapping your router's `Link`), plus `class`, `children`, `ref`, and arbitrary passthrough attributes. `NavigationMenuTrigger` also accepts a `type` override, though it defaults to `"button"` so it never accidentally submits a form.

Edge cases

Multi-level or mega-menu content is entirely on you to lay out inside `NavigationMenuContent` — there's no built-in positioning or collision handling in `NavigationMenuViewport`, it's just a slotted div. Since there's no shipped open state, SSR is trivially safe (everything renders closed/static by default), but that also means client hydration has to attach whatever interaction logic you add. If you need real click-outside dismissal or focus trapping for a flyout, reach for `@askrjs/ui`'s dropdown primitives rather than assuming this package provides it.

See Sidebar and Menubar for the other two navigation-chrome building blocks, Application Chrome for how these fit into a full page shell, and Breadcrumb and Pagination for the smaller wayfinding controls that often sit alongside a nav bar.