# Navigation Menu

**A collection of links and menus for website navigation.**

**Reference:** [View Source](https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Primitives/NavigationMenu) · [Zag.js Docs](https://zagjs.com/components/react/navigation-menu)

**NavigationMenu.html**

```html
<ui:navigationMenu.root withViewport="{true}">
    <ui:navigationMenu.list>
        <ui:navigationMenu.item value="products">
            <ui:navigationMenu.trigger>Products</ui:navigationMenu.trigger>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="company">
            <ui:navigationMenu.trigger>Company</ui:navigationMenu.trigger>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="docs">
            <ui:navigationMenu.link href="#">Documentation</ui:navigationMenu.link>
        </ui:navigationMenu.item>
    </ui:navigationMenu.list>
    <ui:navigationMenu.indicator>
        <ui:navigationMenu.arrow />
    </ui:navigationMenu.indicator>
    <ui:navigationMenu.viewportPositioner>
        <ui:navigationMenu.viewport>
            <ui:navigationMenu.content value="products" class="w-90">
                <div class="grid grid-cols-2">
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Analytics</span>
                        <span class="text-xs text-muted-foreground">Track and analyze data</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Marketing</span>
                        <span class="text-xs text-muted-foreground">Grow your audience</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Automation</span>
                        <span class="text-xs text-muted-foreground">Save time with workflows</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Commerce</span>
                        <span class="text-xs text-muted-foreground">Sell online with ease</span>
                    </ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
            <ui:navigationMenu.content value="company" class="w-32">
                <div class="grid grid-cols-1">
                    <ui:navigationMenu.link value="company" href="#">About Us</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Blog</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Careers</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Press</ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
        </ui:navigationMenu.viewport>
    </ui:navigationMenu.viewportPositioner>
</ui:navigationMenu.root>
```

**NavigationMenu.ts**

```ts
import { mountAll } from 'fluid-primitives';
import { NavigationMenu } from 'fluid-primitives/navigation-menu';

mountAll('navigationMenu', ({ props }) => {
    const navigationMenu = new NavigationMenu(props);
    navigationMenu.init();
    return navigationMenu;
});

```

## Features

- Supports simple inline dropdowns and shared viewport layouts
- Keyboard navigation with arrow keys, `Home`, and `End`
- Supports trigger-based menus and direct navigation links in the same list
- Animated indicator and shared viewport support
- Supports horizontal and vertical orientation

## Installation

```bash
typo3 ui:add navigation-menu
```

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives.com/tree/main/packages/docs/Resources/Private/Registry/NavigationMenu) into your project.

Read more about installing [Components and Primitives](/docs/core-concepts/primitives.md).

## Examples

### Simple Dropdown

Render navigation items with inline dropdown content.

**NavigationMenu.html**

```html
<ui:navigationMenu.root>
    <ui:navigationMenu.list>
        <ui:navigationMenu.item value="products">
            <ui:navigationMenu.trigger>Products</ui:navigationMenu.trigger>
            <ui:navigationMenu.content>
                <div class="grid grid-cols-1">
                    <ui:navigationMenu.link href="#">Overview</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Features</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Pricing</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Changelog</ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="company">
            <ui:navigationMenu.trigger>Company</ui:navigationMenu.trigger>
            <ui:navigationMenu.content>
                <div class="grid grid-cols-1">
                    <ui:navigationMenu.link href="#">About</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Blog</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Careers</ui:navigationMenu.link>
                    <ui:navigationMenu.link href="#">Press</ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="docs">
            <ui:navigationMenu.link href="#">Documentation</ui:navigationMenu.link>
        </ui:navigationMenu.item>
    </ui:navigationMenu.list>
</ui:navigationMenu.root>
```

### Links Only

Use the navigation menu as a simple list of links, including a current page link.

**NavigationMenu.html**

```html
<ui:navigationMenu.root>
    <ui:navigationMenu.list>
        <ui:navigationMenu.item value="home">
            <ui:navigationMenu.link href="/" current="{true}">Home</ui:navigationMenu.link>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="docs">
            <ui:navigationMenu.link href="/docs">Docs</ui:navigationMenu.link>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="github">
            <ui:navigationMenu.link href="/github">GitHub</ui:navigationMenu.link>
        </ui:navigationMenu.item>
    </ui:navigationMenu.list>
</ui:navigationMenu.root>
```

### With Viewport

Use `withViewport="{true}"` to render dropdown content inside a shared viewport. This pattern works well for richer header navigation with animated transitions and an indicator.

**NavigationMenu.html**

```html
<ui:navigationMenu.root withViewport="{true}">
    <ui:navigationMenu.list>
        <ui:navigationMenu.item value="products">
            <ui:navigationMenu.trigger>Products</ui:navigationMenu.trigger>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="company">
            <ui:navigationMenu.trigger>Company</ui:navigationMenu.trigger>
        </ui:navigationMenu.item>
        <ui:navigationMenu.item value="docs">
            <ui:navigationMenu.link href="#">Documentation</ui:navigationMenu.link>
        </ui:navigationMenu.item>
    </ui:navigationMenu.list>
    <ui:navigationMenu.indicator>
        <ui:navigationMenu.arrow />
    </ui:navigationMenu.indicator>
    <ui:navigationMenu.viewportPositioner>
        <ui:navigationMenu.viewport>
            <ui:navigationMenu.content value="products" class="w-90">
                <div class="grid grid-cols-2">
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Analytics</span>
                        <span class="text-xs text-muted-foreground">Track and analyze data</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Marketing</span>
                        <span class="text-xs text-muted-foreground">Grow your audience</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Automation</span>
                        <span class="text-xs text-muted-foreground">Save time with workflows</span>
                    </ui:navigationMenu.link>
                    <ui:navigationMenu.link value="products" href="#" class="flex flex-col gap-0.5 !py-2 !px-3">
                        <span class="font-medium text-sm">Commerce</span>
                        <span class="text-xs text-muted-foreground">Sell online with ease</span>
                    </ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
            <ui:navigationMenu.content value="company" class="w-32">
                <div class="grid grid-cols-1">
                    <ui:navigationMenu.link value="company" href="#">About Us</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Blog</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Careers</ui:navigationMenu.link>
                    <ui:navigationMenu.link value="company" href="#">Press</ui:navigationMenu.link>
                </div>
            </ui:navigationMenu.content>
        </ui:navigationMenu.viewport>
    </ui:navigationMenu.viewportPositioner>
</ui:navigationMenu.root>
```

## API Reference

### navigationMenu.root

Provides shared navigation menu state and semantics. Renders a `<nav>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `orientation` | `Enum\Orientation` | No | `Horizontal` | The orientation of the navigation menu. |
| `defaultValue` | `string` | No | `''` | The default value of the navigation menu. Use when you don't want to control the value of the menu. |
| `openDelay` | `integer` | No | `200` | The delay before the menu opens. |
| `closeDelay` | `integer` | No | `300` | The delay before the menu closes. |
| `disableHoverTrigger` | `boolean` | No | `-` | Whether to disable the hover trigger. |
| `disableClickTrigger` | `boolean` | No | `-` | Whether to disable the click trigger. |
| `disablePointerLeaveClose` | `boolean` | No | `-` | Whether to disable the pointer leave close. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `rootId` | `string` | No | `-` | The root ID of the component, used for hydration and identification. |
| `ids` | `array` | No | `[]` | The IDs of of the component parts for composition. |
| `controlled` | `boolean` | No | `false` | If true, the component is meant to be initialized manually inside another component |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | root |
| `data-orientation` | The orientation of the navigation-menu |

### navigationMenu.list

Groups the top-level navigation items. Renders a `<ul>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | list |
| `data-orientation` | The orientation of the list |

### navigationMenu.item

Wraps a single navigation item and its related parts. Renders an `<li>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | Yes | `-` | The value of the item. |
| `disabled` | `boolean` | No | `-` | Whether the item is disabled. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | item |
| `data-value` | The value of the item |
| `data-state` | "open" \| "closed" |
| `data-orientation` | The orientation of the item |
| `data-disabled` | Present when disabled |

### navigationMenu.trigger

Opens and closes the related navigation content. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | trigger |
| `data-trigger-proxy-id` |  |
| `data-value` | The value of the item |
| `data-state` | "open" \| "closed" |
| `data-disabled` | Present when disabled |

### navigationMenu.triggerProxy

Provides a hidden focus proxy for shared viewport behavior. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | trigger-proxy |
| `data-trigger-proxy` |  |
| `data-trigger-id` |  |

### navigationMenu.link

Renders a navigational link item. Renders an `<a>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | No | `-` | The value of the item this link belongs to. By default this is inherited from the parent navigationMenu.item. |
| `current` | `boolean` | No | `-` | Whether the link is the current page. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | link |
| `data-value` | The value of the item |
| `data-current` | Present when current |

### navigationMenu.indicatorTrack

Provides a track for the active-item indicator. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

### navigationMenu.indicator

Displays the shared active-item indicator. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | indicator |
| `data-state` | "open" \| "closed" |
| `data-orientation` | The orientation of the indicator |

### navigationMenu.itemIndicator

Displays an indicator for an open item. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | item-indicator |
| `data-state` | "open" \| "closed" |
| `data-orientation` | The orientation of the item |
| `data-value` | The value of the item |

### navigationMenu.content

Contains the popup content for a navigation item. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | No | `-` | The value of the item this content belongs to. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | content |
| `data-state` | "open" \| "closed" |
| `data-orientation` | The orientation of the content |
| `data-value` | The value of the item |

### navigationMenu.viewportPositioner

Positions the shared viewport element. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `align` | `Enum\NavigationMenuAlign` | No | `Center` | Placement of the viewport for CSS variables `--viewport-x` and `--viewport-y`. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | viewport-positioner |
| `data-orientation` | The orientation of the viewportpositioner |
| `data-align` |  |

### navigationMenu.viewport

Displays the shared viewport that can host item content. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | viewport |
| `data-state` | "open" \| "closed" |
| `data-orientation` | The orientation of the viewport |
| `data-align` |  |

### navigationMenu.viewportProxy

Provides a proxy element used to size and align the viewport. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

### navigationMenu.arrow

Displays a decorative arrow for the indicator or content. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | navigation-menu |
| `data-part` | arrow |
| `data-orientation` | The orientation of the arrow |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `value` | `string \| null` | The current value of the menu |
| `setValue` | `(value: string) => void` | Sets the value of the menu |
| `open` | `boolean` | Whether the menu is open |
| `isViewportRendered` | `boolean` | Whether the viewport is rendered |
| `getViewportNode` | `() => HTMLElement \| null` | Gets the viewport node element |
| `orientation` | `Orientation` | The orientation of the menu |
| `reposition` | `VoidFunction` | Function to reposition the viewport |

### Accessibility

| Key | Description |
| --- | --- |
| `ArrowDown`  | When focus is on trigger (vertical orientation), moves focus to the next trigger. |
| `ArrowUp`  | When focus is on trigger (vertical orientation), moves focus to the previous trigger. |
| `ArrowRight`  | <span>When focus is on trigger (horizontal orientation), moves focus to the next trigger.<br />When focus is on content, moves focus to the next link.</span> |
| `ArrowLeft`  | <span>When focus is on trigger (horizontal orientation), moves focus to the previous trigger.<br />When focus is on content, moves focus to the previous link.</span> |
| `Home`  | <span>When focus is on trigger, moves focus to the first trigger.<br />When focus is on content, moves focus to the first link.</span> |
| `End`  | <span>When focus is on trigger, moves focus to the last trigger.<br />When focus is on content, moves focus to the last link.</span> |

## Anatomy

```html
<primitives:navigationMenu.root>
    <primitives:navigationMenu.list>
        <primitives:navigationMenu.item>
            <primitives:navigationMenu.trigger />
            <primitives:navigationMenu.content>
                <primitives:navigationMenu.link />
            </primitives:navigationMenu.content>
        </primitives:navigationMenu.item>

        <primitives:navigationMenu.item>
            <primitives:navigationMenu.link />
        </primitives:navigationMenu.item>
    </primitives:navigationMenu.list>
</primitives:navigationMenu.root>
```

When using the shared viewport pattern, add the optional viewport-related parts:

```html
<primitives:navigationMenu.root>
    <primitives:navigationMenu.list>
        <primitives:navigationMenu.item>
            <primitives:navigationMenu.trigger />
            <primitives:navigationMenu.triggerProxy />
            <primitives:navigationMenu.viewportProxy />
        </primitives:navigationMenu.item>
    </primitives:navigationMenu.list>

    <primitives:navigationMenu.indicator>
        <primitives:navigationMenu.arrow />
    </primitives:navigationMenu.indicator>

    <primitives:navigationMenu.viewportPositioner>
        <primitives:navigationMenu.viewport>
            <primitives:navigationMenu.content>
                <primitives:navigationMenu.link />
            </primitives:navigationMenu.content>
        </primitives:navigationMenu.viewport>
    </primitives:navigationMenu.viewportPositioner>
</primitives:navigationMenu.root>
```
