# NavigationMenu

> Marketing-site header menu on Base UI NavigationMenu, with chevron triggers, a shared animated panel, link lists and a featured card slot. Works in RTL.

Source: https://docs.nasaqui.com/components/navigation-menu

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/navigation-menu.json
```

The header menu of a marketing site: a row of triggers and links, where each trigger opens a panel of links and
an optional featured card. The panel is one shared viewport, so moving from one trigger to the next resizes and
slides the panel instead of closing and reopening it. These are links to pages, not commands.

## When to use

- A website header with grouped links, descriptions and a featured item (a mega menu).
- Navigation where every entry is a URL.

## When not to use

- Commands in an application window: use [`Menubar`](https://docs.nasaqui.com/components/menubar).
- A list of actions behind a button: use [`DropdownMenu`](https://docs.nasaqui.com/components/dropdown-menu).
- Switching views inside a page: use [`Tabs`](https://docs.nasaqui.com/components/tabs).
- A sidebar for an app: use `SidebarLayout` from [`AppShell`](https://docs.nasaqui.com/components/app-shell).

## Import

```tsx
import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkItem,
  NavigationMenuLinkList,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@fadymondy/nasaq/web";

export function SiteNav() {
  return (
    <NavigationMenu aria-label="Main">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
          <NavigationMenuContent className="w-72">
            <NavigationMenuLinkList>
              <NavigationMenuLinkItem href="/docs" title="Documentation" description="Guides and API reference." />
              <NavigationMenuLinkItem href="/blog" title="Blog" description="Product news." />
            </NavigationMenuLinkList>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="/pricing">Pricing</NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}
```

## Anatomy

```
NavigationMenu                          data-slot="navigation-menu"  (nav)
├─ NavigationMenuList                   data-slot="navigation-menu-list"
│  ├─ NavigationMenuItem
│  │  ├─ NavigationMenuTrigger          data-slot="navigation-menu-trigger" (with chevron)
│  │  └─ NavigationMenuContent          data-slot="navigation-menu-content"
│  │     ├─ NavigationMenuLayout        data-slot="navigation-menu-layout"
│  │     ├─ NavigationMenuLabel         data-slot="navigation-menu-label"
│  │     ├─ NavigationMenuLinkList      data-slot="navigation-menu-link-list"
│  │     │  └─ NavigationMenuLinkItem   data-slot="navigation-menu-link-item" (li > a)
│  │     └─ NavigationMenuFeatured      data-slot="navigation-menu-featured" (a)
│  └─ NavigationMenuItem > NavigationMenuLink   data-slot="navigation-menu-link"
└─ (rendered for you) positioner > popup > viewport   data-slot="navigation-menu-positioner" | "navigation-menu-popup" | "navigation-menu-viewport"
```

## API

**NavigationMenu**: Base UI `NavigationMenu.Root` props (`value`, `defaultValue`, `onValueChange`, `delay`, `closeDelay`, `orientation`) plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `align` | `"start" \| "center" \| "end"` | `"start"` | Where the shared panel sits against the active trigger. |
| `sideOffset` | `number` | `8` | Gap between the bar and the panel. |
| `panelClassName` | `string` | | Class for the panel. |

**NavigationMenuList, NavigationMenuItem**: the Base UI list and item. `NavigationMenuItem` is unchanged.

**NavigationMenuTrigger**: Base UI trigger with the bar style and a chevron that rotates while open.

**NavigationMenuLink**: a top-level link in the bar. Takes `href` and Base UI `active`. Use the `render` prop for a router link.

**NavigationMenuContent**: the panel body. Sets the slide and fade. Set the width with `className` (`w-72`).

**NavigationMenuLinkList**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `columns` | `1 \| 2 \| 3` | `1` | Columns from the `sm` breakpoint. |

**NavigationMenuLinkItem** (`NavigationMenuLinkItemProps`): Base UI link props except `title`, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `ReactNode` | | Link title. |
| `description` | `ReactNode` | | One line under the title. |
| `icon` | `ReactNode` | | Icon at the inline start. Decorative. |

**NavigationMenuFeatured**: a link styled as a card, for the featured slot. Takes `href` and any children.

**NavigationMenuLayout**: a flex row (column on small screens) that places a link list and a featured card side by side. DOM order is visual order.

**NavigationMenuLabel**: a small heading above a link list.

## Examples

**Mega menu with a featured card**

```tsx
import {
  Badge,
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuFeatured,
  NavigationMenuItem,
  NavigationMenuLayout,
  NavigationMenuLinkItem,
  NavigationMenuLinkList,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@fadymondy/nasaq/web";

export function ProductMenu() {
  return (
    <NavigationMenu aria-label="Main">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Product</NavigationMenuTrigger>
          <NavigationMenuContent>
            <NavigationMenuLayout>
              <NavigationMenuLinkList className="w-80">
                <NavigationMenuLinkItem href="/automation" title="Automation" description="Rules that move work along." />
                <NavigationMenuLinkItem href="/analytics" title="Analytics" description="Dashboards for time and cost." />
              </NavigationMenuLinkList>
              <NavigationMenuFeatured href="/release">
                <Badge>New</Badge>
                <span className="text-label text-foreground">Nasaq 2.0 is here</span>
                <span className="text-body-sm text-muted-foreground">A design system for Arabic-first products.</span>
              </NavigationMenuFeatured>
            </NavigationMenuLayout>
          </NavigationMenuContent>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}
```

**Arabic**

```tsx
import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLinkItem, NavigationMenuLinkList, NavigationMenuList, NavigationMenuTrigger } from "@fadymondy/nasaq/web";

export function ArabicNav() {
  return (
    <NavigationMenu aria-label="الرئيسية">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>المصادر</NavigationMenuTrigger>
          <NavigationMenuContent className="w-72">
            <NavigationMenuLinkList>
              <NavigationMenuLinkItem href="/docs" title="التوثيق" description="أدلة ومرجع الواجهات." />
            </NavigationMenuLinkList>
          </NavigationMenuContent>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}
```

**Router links**

```tsx
import { NavigationMenuLink } from "@fadymondy/nasaq/web";

// Pass your framework's link through `render`.
export function RouterLink() {
  return <NavigationMenuLink render={<a href="/pricing" />}>Pricing</NavigationMenuLink>;
}
```

## Accessibility

| Key | Action |
| --- | --- |
| Left / Right | Moves between triggers and links in the bar. Swapped in RTL. |
| Down / Enter / Space | Opens the panel of the focused trigger. |
| Tab | Moves into the open panel's links, then on. |
| Escape | Closes the panel and returns focus to its trigger. |

- The root is a `nav`; give it an `aria-label`. Triggers have `aria-expanded`. The current page link takes `active`, which sets `aria-current="page"`.
- Hover opens a panel after a short delay; touch and keyboard open it on press.
- The caller must localise the `aria-label` and all link text.

## RTL & i18n

- The bar starts at the inline start (the right in Arabic) and the panel aligns to its trigger's start edge.
- ArrowLeft moves to the next trigger in Arabic. The `sm:flex-row` layout puts the first child at the right.
- Panel content slides by the side the previous panel was on. Reduced motion turns every transition off.

## Styling & tokens

- Panel: `popover`, `border`, `shadow-floating`, `rounded-floating`. Triggers and links: `nq-hover`, `nq-selected`, `nq-focus`. Featured card: `nq-surface-soft`.
- State attributes: `data-popup-open` on the trigger, `data-starting-style` and `data-ending-style` on the panel, `data-activation-direction` on the content, `data-active` on a current link.
- Extend with `className` and `panelClassName`. Use tokens, never raw hex.

## Do / Don't

- Do keep panels to one link list, and one featured card at most.
- Do give every link a description of one line.
- Don't use it for actions or commands: use `Menubar` or `DropdownMenu`.
- Don't nest a second menu inside a panel.

## Related

- [`Menubar`](https://docs.nasaqui.com/components/menubar)
- [`DropdownMenu`](https://docs.nasaqui.com/components/dropdown-menu)
- [`Tabs`](https://docs.nasaqui.com/components/tabs)

## Lab

https://docs.nasaqui.com/?path=/docs/components-navigation-navigation-menu--docs

## Code

### React

```tsx
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkItem,
  NavigationMenuLinkList,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@fadymondy/nasaq/web";

export function SiteNav() {
  return (
    <NavigationMenu aria-label="Main">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
          <NavigationMenuContent className="w-72">
            <NavigationMenuLinkList>
              <NavigationMenuLinkItem href="/docs" title="Documentation" description="Guides and API reference." />
              <NavigationMenuLinkItem href="/blog" title="Blog" description="Product news." />
            </NavigationMenuLinkList>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="/pricing">Pricing</NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}
```

### shadcn

```tsx
import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuLinkItem, NavigationMenuLinkList, NavigationMenuList, NavigationMenuTrigger } from "@/components/ui/navigation-menu";

export function SiteNav() {
  return (
    <NavigationMenu aria-label="Main">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
          <NavigationMenuContent className="w-72">
            <NavigationMenuLinkList>
              <NavigationMenuLinkItem href="/docs" title="Documentation" description="Guides and API reference." />
              <NavigationMenuLinkItem href="/blog" title="Blog" description="Product news." />
            </NavigationMenuLinkList>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="/pricing">Pricing</NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import {
  NqNavigationMenu,
  NqNavigationMenuContent,
  NqNavigationMenuItem,
  NqNavigationMenuLink,
  NqNavigationMenuLinkItem,
  NqNavigationMenuLinkList,
  NqNavigationMenuList,
  NqNavigationMenuTrigger,
} from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqNavigationMenu aria-label="Main">
    <NqNavigationMenuList>
      <NqNavigationMenuItem>
        <NqNavigationMenuTrigger>Resources</NqNavigationMenuTrigger>
        <NqNavigationMenuContent class="w-72">
          <NqNavigationMenuLinkList>
            <NqNavigationMenuLinkItem href="/docs" title="Documentation" description="Guides and API reference." />
            <NqNavigationMenuLinkItem href="/blog" title="Blog" description="Product news." />
          </NqNavigationMenuLinkList>
        </NqNavigationMenuContent>
      </NqNavigationMenuItem>
      <NqNavigationMenuItem>
        <NqNavigationMenuLink href="/pricing">Pricing</NqNavigationMenuLink>
      </NqNavigationMenuItem>
    </NqNavigationMenuList>
  </NqNavigationMenu>
</template>
```

### Blade

```blade
<x-nq::navigation-menu aria-label="Main">
    <x-nq::navigation-menu.list>
        <x-nq::navigation-menu.item value="resources">
            <x-nq::navigation-menu.trigger>Resources</x-nq::navigation-menu.trigger>
            <x-nq::navigation-menu.content class="w-72">
                <x-nq::navigation-menu.link-list>
                    <x-nq::navigation-menu.link-item href="/docs" title="Documentation" description="Guides and API reference." />
                    <x-nq::navigation-menu.link-item href="/blog" title="Blog" description="Product news." />
                </x-nq::navigation-menu.link-list>
            </x-nq::navigation-menu.content>
        </x-nq::navigation-menu.item>
        <x-nq::navigation-menu.item>
            <x-nq::navigation-menu.link href="/pricing">Pricing</x-nq::navigation-menu.link>
        </x-nq::navigation-menu.item>
    </x-nq::navigation-menu.list>
</x-nq::navigation-menu>
```

### HTML + Alpine

```html
<nav data-slot="navigation-menu" x-data="nqNavigationMenu(null)" x-bind="root" data-align="start"
    aria-label="Main" class="relative flex w-max max-w-full">
    <ul data-slot="navigation-menu-list" x-bind="list" class="relative m-0 flex list-none items-center gap-0.5 p-0"><li data-slot="navigation-menu-item" class="relative"><button data-slot="navigation-menu-trigger" x-bind="trigger('resources')" aria-expanded="false"
    class="inline-flex h-control min-h-[var(--nq-touch-min,0px)] select-none items-center justify-center gap-1.5 rounded-control px-3 text-label text-foreground no-underline outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover data-popup-open:bg-nq-selected data-pressed:bg-nq-selected focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus">
    Resources
    <span x-bind:data-popup-open="value === 'resources' ? '' : undefined"
        class="inline-flex transition-transform duration-200 ease-nq data-popup-open:rotate-180 motion-reduce:transition-none"><svg aria-hidden="true" class="size-4 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></span>
</button>
            <div data-slot="navigation-menu-content" x-bind="content('resources')" style="display: none"
    class="h-full min-w-64 max-w-[min(100vw-2rem,52rem)] p-3 transition-[opacity,translate] duration-300 ease-nq motion-reduce:transition-none data-starting-style:opacity-0 data-ending-style:opacity-0 data-starting-style:data-[activation-direction=left]:-translate-x-1/2 data-starting-style:data-[activation-direction=right]:translate-x-1/2 data-ending-style:data-[activation-direction=left]:translate-x-1/2 data-ending-style:data-[activation-direction=right]:-translate-x-1/2 w-72"><ul data-slot="navigation-menu-link-list"
    class="m-0 grid list-none gap-1 p-0"><li data-slot="navigation-menu-link-item" class="m-0 list-none">
    <a href="/docs"         class="flex items-start gap-3 rounded-control p-2.5 text-start no-underline outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-active:bg-nq-selected">
                <span class="flex min-w-0 flex-col gap-0.5">
            <span class="text-label text-foreground">Documentation</span>
            <span class="text-body-sm text-muted-foreground">Guides and API reference.</span>        </span>
    </a>
</li>
                    <li data-slot="navigation-menu-link-item" class="m-0 list-none">
    <a href="/blog"         class="flex items-start gap-3 rounded-control p-2.5 text-start no-underline outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-active:bg-nq-selected">
                <span class="flex min-w-0 flex-col gap-0.5">
            <span class="text-label text-foreground">Blog</span>
            <span class="text-body-sm text-muted-foreground">Product news.</span>        </span>
    </a>
</li></ul></div></li>
        <li data-slot="navigation-menu-item" class="relative"><a data-slot="navigation-menu-link" href="/pricing"     class="inline-flex h-control min-h-[var(--nq-touch-min,0px)] select-none items-center justify-center gap-1.5 rounded-control px-3 text-label text-foreground no-underline outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover data-popup-open:bg-nq-selected data-pressed:bg-nq-selected focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-active:bg-nq-selected">Pricing</a></li></ul>
    <div data-slot="navigation-menu-positioner" data-side="bottom" data-align="start" style="display: none; margin-top: 8px; --available-width: calc(100vw - 2rem)"
        class="absolute left-0 top-full z-50 h-[var(--positioner-height)] w-[var(--positioner-width)] max-w-[var(--available-width)] transition-[inset] duration-300 ease-nq motion-reduce:transition-none data-instant:transition-none before:absolute before:inset-x-0 before:-top-2 before:h-2 before:content-['']">
        <div data-slot="navigation-menu-popup" style="--transform-origin: top"
            class="relative h-[var(--popup-height)] w-[var(--popup-width)] origin-[var(--transform-origin)] overflow-hidden rounded-floating border border-border bg-popover text-popover-foreground shadow-floating outline-none transition-[opacity,scale,width,height] duration-300 ease-nq motion-reduce:transition-none data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 data-ending-style:duration-150">
            <div data-slot="navigation-menu-viewport" class="relative h-full w-full overflow-hidden"></div>
        </div>
    </div>
</nav>
```
