# NavigationMenu Primitive

Navigation Menu coordinates a single active top-level item, shared viewport content, hover timing, keyboard movement, and link close behavior for site navigation.
## Usage Guidelines
- **Use Navigation Menu for top-level site or product navigation.** Use it when a row or column of triggers reveals rich panels that share one viewport.
- **Use Menu or Popover for isolated actions.** Navigation Menu is value-driven and viewport-driven, so it is heavier than a single contextual popup.
## Anatomy
### Astro
Use the Astro primitive adapter to render NavigationMenu anatomy with the Runtime wiring included.
```astro
---
import { NavigationMenu } from "@starwind-ui/astro/navigation-menu";
---

<NavigationMenu.Root>
  <NavigationMenu.List>
    <NavigationMenu.Item value="products">
      <NavigationMenu.Trigger>
        <NavigationMenu.Icon>v</NavigationMenu.Icon>
      </NavigationMenu.Trigger>
      <NavigationMenu.Content>
        <NavigationMenu.Link href="/docs">Docs</NavigationMenu.Link>
      </NavigationMenu.Content>
    </NavigationMenu.Item>
  </NavigationMenu.List>
  <NavigationMenu.Portal>
    <NavigationMenu.Positioner>
      <NavigationMenu.Popup>
        <NavigationMenu.Viewport />
        <NavigationMenu.Arrow />
      </NavigationMenu.Popup>
    </NavigationMenu.Positioner>
  </NavigationMenu.Portal>
</NavigationMenu.Root>
```

### React
Use the React primitive adapter when NavigationMenu state participates in React rendering.
```tsx
import { NavigationMenu } from "@starwind-ui/react/navigation-menu";

export function Example() {
  return (
    <NavigationMenu.Root>
      <NavigationMenu.List>
        <NavigationMenu.Item value="products">
          <NavigationMenu.Trigger>
            <NavigationMenu.Icon>v</NavigationMenu.Icon>
          </NavigationMenu.Trigger>
          <NavigationMenu.Content>
            <NavigationMenu.Link href="/docs">Docs</NavigationMenu.Link>
          </NavigationMenu.Content>
        </NavigationMenu.Item>
      </NavigationMenu.List>
      <NavigationMenu.Portal>
        <NavigationMenu.Positioner>
          <NavigationMenu.Popup>
            <NavigationMenu.Viewport />
            <NavigationMenu.Arrow />
          </NavigationMenu.Popup>
        </NavigationMenu.Positioner>
      </NavigationMenu.Portal>
    </NavigationMenu.Root>
  );
}
```

### HTML
Render the NavigationMenu data-sw-* contract yourself, then initialize createNavigationMenu.
```html
<nav data-sw-nav-menu>
  <ul data-sw-nav-menu-list>
    <li data-sw-nav-menu-item data-value="products">
      <button data-sw-nav-menu-trigger type="button" aria-haspopup="menu">
        <span data-sw-nav-menu-icon aria-hidden="true">v</span>
      </button>
      <div data-sw-nav-menu-content hidden>
        <a data-sw-nav-menu-link href="/docs">Docs</a>
      </div>
    </li>
  </ul>
  <div data-sw-nav-menu-portal>
    <div data-sw-nav-menu-positioner>
      <div data-sw-nav-menu-popup hidden>
        <div data-sw-nav-menu-viewport hidden></div>
        <div data-sw-nav-menu-arrow aria-hidden="true"></div>
      </div>
    </div>
  </div>
</nav>

<script type="module">
  import { createNavigationMenu } from "@starwind-ui/runtime/navigation-menu";

  const root = document.querySelector("[data-sw-nav-menu]");
  if (root) {
    createNavigationMenu(root);
  }
</script>
```
## Shared Viewport
Content panels are authored inside items, then moved into the shared viewport while active so the popup can animate size and direction consistently.
## Floating Behavior
| Fact | Value |
| --- | --- |
| Anchor part | trigger |
| Positioner part | positioner |
| Popup part | popup |
| Portal part | portal |
| Option props | side, align, sideOffset, alignOffset, avoidCollisions, collisionPadding |
## API Reference
### Root
The navigation landmark that owns the active value, orientation, hover timing, dismissal options, and Runtime instance.
| Fact | Value |
| --- | --- |
| Default element | `nav` |
| Discovery hook | `data-sw-nav-menu` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| value | `string \| null` | - | control | Controls the active item value when a framework adapter owns state. |
| defaultValue | `string \| null` | null | control | Sets the initial uncontrolled active item value. |
| openDelay | `number` | 50 | option | Sets the default hover-open delay in milliseconds. |
| closeDelay | `number` | 50 | option | Sets the default hover-close delay in milliseconds. |
| closeOnEscape | `boolean` | true | option | Closes NavigationMenu when Escape is pressed. |
| closeOnOutsideInteract | `boolean` | true | option | Closes NavigationMenu when the user interacts outside it. |
| onValueChange | `(value: string \| null, details: NavigationMenuValueChangeDetails) => void` | - | callback | Runs when the NavigationMenu value changes. |
| orientation | `"horizontal" \| "vertical"` | "horizontal" | option | Sets horizontal or vertical trigger keyboard movement. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu` | runtime | - | Runtime discovery hook for the Navigation Menu root. |
| `data-value` | prop | - | Reflects the value prop on the Root part. |
| `data-controlled-value` | prop | - | Reflects the controlled value prop on the Root part. |
| `data-default-value` | prop | - | Initial uncontrolled active item value. |
| `data-open-delay` | prop | - | Reflects the open delay prop on the Root part. |
| `data-close-delay` | prop | - | Reflects the close delay prop on the Root part. |
| `data-close-on-escape` | prop | - | Reflects the close on escape prop on the Root part. |
| `data-close-on-outside-interact` | prop | - | Reflects the close on outside interact prop on the Root part. |
| `data-orientation` | prop | - | Reflects the orientation prop on the Root part. |
| `data-state` | state | - | Reflects whether any item is open. |
#### State
| State | Value Type | Controlled Prop | Default Prop | Initial Attribute | Runtime Getter | Runtime Setter | Description | State Control Support |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| value | `string \| null` | value | defaultValue | `data-default-value` | `getValue` | `setValue` | Tracks the current NavigationMenu value. | React supports controlled and default state with value and defaultValue props. Runtime/HTML reads initial state from data-default-value, emits starwind:value-change, and updates with setValue. Astro adapters render initial/default state, but do not expose reactive controlled-state props for this state. |
#### Events
| Event | Callback | DOM Event | Value | Details | Timing | Cancelable | Description |
| --- | --- | --- | --- | --- | --- | --- | --- |
| valueChange | onValueChange | starwind:value-change | value: `string \| null` | NavigationMenuValueChangeDetails | before-state-commit | Yes | Fires when the value changes for NavigationMenu. |
#### Runtime Setters
| Method | Target | Options | Suppresses Emit | Description |
| --- | --- | --- | --- | --- |
| `setValue` | state: value | emit: false | Yes | Updates the current NavigationMenu value from Runtime code. |
#### Refs
| Part | Public |
| --- | --- |
| root | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu`, `data-default-value`, `data-open-delay`, `data-close-delay`, `data-close-on-escape`, `data-close-on-outside-interact`, `data-orientation`, `data-state` | The root needs initial value, dismissal, orientation, and closed state before hydration. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | No |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### List
The list of selectable NavigationMenu items.
| Fact | Value |
| --- | --- |
| Default element | `ul` |
| Discovery hook | `data-sw-nav-menu-list` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-list` | runtime | - | Marks the List part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| list | Yes |

### Item
An interactive item inside the NavigationMenu collection.
| Fact | Value |
| --- | --- |
| Default element | `li` |
| Discovery hook | `data-sw-nav-menu-item` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| value | `string` | - | option | Controls the current NavigationMenu value. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-item` | runtime | - | Marks the Item part so Starwind Runtime can find it. |
| `data-value` | prop | - | Reflects the value prop on the Item part. |
| `data-state` | state | - | Reflects the current state on the Item part. |
#### Refs
| Part | Public |
| --- | --- |
| item | Yes |

### Trigger
The button or asChild control that opens, closes, and keyboard-targets a content panel.
| Fact | Value |
| --- | --- |
| Default element | `button` |
| Discovery hook | `data-sw-nav-menu-trigger` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| openDelay | `number` | 50 | option | Overrides root hover-open timing for this trigger. |
| closeDelay | `number` | 50 | option | Overrides root hover-close timing for this trigger. |
| asChild | `boolean` | - | rendering | Merges trigger behavior into the slotted child control. |
| disabled | `boolean` | false | option | Prevents trigger interaction and removes it from roving trigger movement. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-trigger` | runtime | - | Runtime discovery hook for the trigger part. |
| `data-as-child` | prop | - | Reflects the as child prop on the Trigger part. |
| `data-open-delay` | prop | - | Reflects the open delay prop on the Trigger part. |
| `data-close-delay` | prop | - | Reflects the close delay prop on the Trigger part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Trigger part. |
| `data-state` | state | - | Reflects whether this trigger's item is open. |
#### Refs
| Part | Public |
| --- | --- |
| trigger | Yes |
#### asChild
| Part | Merged Props |
| --- | --- |
| trigger | aria, className, data, ref, style |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu-trigger`, `type`, `data-as-child`, `data-open-delay`, `data-close-delay`, `aria-haspopup`, `aria-expanded`, `data-disabled`, `data-state` | Triggers need button semantics and closed ARIA state before hydration. |

### Icon
Decorative icon rendered by NavigationMenu.
| Fact | Value |
| --- | --- |
| Default element | `span` |
| Discovery hook | `data-sw-nav-menu-icon` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-icon` | runtime | - | Marks the Icon part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Icon part. |
#### Refs
| Part | Public |
| --- | --- |
| icon | Yes |

### Content
The authored item panel. The Runtime moves the active content into the shared viewport.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-content` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-content` | runtime | - | Runtime discovery hook for the content part. |
| `data-state` | state | - | Reflects whether this content panel is active. |
#### Refs
| Part | Public |
| --- | --- |
| content | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu-content`, `data-state`, `hidden` | Content starts hidden until the runtime moves the active panel into the viewport. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | Yes |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### Link
A navigation link inside content. Links close the active menu by default and can mark current-page state.
| Fact | Value |
| --- | --- |
| Default element | `a` |
| Discovery hook | `data-sw-nav-menu-link` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| href | `string` | - | attribute | Sets the href attribute on the Link part. |
| active | `boolean` | false | option | Marks the link as active and sets aria-current. |
| closeOnClick | `boolean` | true | option | Controls whether clicking the link closes the menu. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-link` | runtime | - | Runtime discovery hook for the link part. |
| `data-active` | prop | - | Present when the link is active. |
| `data-close-on-click` | prop | - | Set to false to keep the menu open after link activation. |
#### Refs
| Part | Public |
| --- | --- |
| link | Yes |

### Portal
Moves NavigationMenu overlay content to the document body when needed.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-portal` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-portal` | runtime | - | Marks the Portal part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| portal | Yes |

### Positioner
The floating positioning part for the shared popup.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-positioner` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| side | `"top" \| "right" \| "bottom" \| "left"` | "bottom" | option | Sets the preferred side for the popup. |
| align | `"start" \| "center" \| "end"` | "start" | option | Sets popup alignment relative to the active trigger. |
| sideOffset | `number` | 4 | option | Sets the distance between the popup and trigger. |
| alignOffset | `number` | 0 | option | Adjusts the cross-axis alignment offset for NavigationMenu content. |
| avoidCollisions | `boolean` | true | option | Allows the popup to shift or flip to remain visible. |
| collisionPadding | `number` | 8 | option | Configures the collision padding option for the Positioner part. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-positioner` | runtime | - | Runtime discovery hook for the positioner part. |
| `data-state` | state | - | Reflects the current state on the Positioner part. |
| `data-side` | prop | - | Reflects the resolved floating side. |
| `data-align` | prop | - | Reflects the resolved floating alignment. |
| `data-side-offset` | prop | - | Reflects the side offset prop on the Positioner part. |
| `data-align-offset` | prop | - | Reflects the align offset prop on the Positioner part. |
| `data-avoid-collisions` | prop | - | Reflects the avoid collisions prop on the Positioner part. |
| `data-collision-padding` | prop | - | Reflects the collision padding prop on the Positioner part. |
#### Refs
| Part | Public |
| --- | --- |
| positioner | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu-positioner`, `data-state`, `data-side`, `data-align`, `data-side-offset`, `data-align-offset`, `data-avoid-collisions`, `data-collision-padding` | The positioner owns initial floating options before hydration. |

### Popup
The floating content container for NavigationMenu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-popup` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description |
| --- | --- | --- | --- | --- |
| side | `"top" \| "right" \| "bottom" \| "left"` | "bottom" | option | Sets the preferred side for NavigationMenu content. |
| align | `"start" \| "center" \| "end"` | "start" | option | Sets how NavigationMenu content aligns to its trigger. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-popup` | runtime | - | Marks the Popup part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Popup part. |
| `data-side` | prop | - | Reflects the side prop on the Popup part. |
| `data-align` | prop | - | Reflects the align prop on the Popup part. |
#### Refs
| Part | Public |
| --- | --- |
| popup | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu-popup`, `data-state`, `hidden` | The popup starts hidden until a trigger activates a panel. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | Yes |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### Viewport
The shared visible container that receives active item content and carries measured size state.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-viewport` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-viewport` | runtime | - | Runtime discovery hook for the viewport part. |
| `data-state` | state | - | Reflects whether any content is visible. |
#### Refs
| Part | Public |
| --- | --- |
| viewport | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-nav-menu-viewport`, `data-state`, `hidden` | The shared viewport starts hidden and receives active content at runtime. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | Yes |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### Arrow
The arrow element that visually points to the trigger.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-nav-menu-arrow` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-nav-menu-arrow` | runtime | - | Marks the Arrow part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Arrow part. |
#### Refs
| Part | Public |
| --- | --- |
| arrow | Yes |
## Runtime API
| Fact | Value |
| --- | --- |
| Factory | [`createNavigationMenu`](/docs/runtime/#create-navigation-menu) |
| Import | `@starwind-ui/runtime/navigation-menu` |
| Root part | root |
| Option props | closeDelay, closeOnEscape, closeOnOutsideInteract, defaultValue, onValueChange, openDelay, value |
| Option lifecycles | closeDelay: constructor-only, closeOnEscape: constructor-only, closeOnOutsideInteract: constructor-only, defaultValue: constructor-only, onValueChange: constructor-only, openDelay: constructor-only, value: setter-backed |
## Related Styled Components
| Component | Relationship |
| --- | --- |
| [Navigation Menu](/docs/components/navigation-menu/) | Direct Primitive |
## Exports
| Group | Import | Exports |
| --- | --- | --- |
| Runtime | `@starwind-ui/runtime/navigation-menu` | `createNavigationMenu` |
| Astro Primitive | `@starwind-ui/astro/navigation-menu` | `NavigationMenu`, `NavigationMenuRoot`, `NavigationMenuList`, `NavigationMenuItem`, `NavigationMenuTrigger`, `NavigationMenuIcon`, `NavigationMenuContent`, `NavigationMenuLink`, `NavigationMenuPortal`, `NavigationMenuPositioner`, `NavigationMenuPopup`, `NavigationMenuViewport`, `NavigationMenuArrow` |
| React Primitive | `@starwind-ui/react/navigation-menu` | `NavigationMenu`, `NavigationMenuRoot`, `NavigationMenuList`, `NavigationMenuItem`, `NavigationMenuTrigger`, `NavigationMenuIcon`, `NavigationMenuContent`, `NavigationMenuLink`, `NavigationMenuPortal`, `NavigationMenuPositioner`, `NavigationMenuPopup`, `NavigationMenuViewport`, `NavigationMenuArrow` |
## Canonical Names
| Kind | Name |
| --- | --- |
| namespace | `NavigationMenu` |
| runtime-factory | `createNavigationMenu` |
| part | `NavigationMenu.Root` |
| part | `NavigationMenu.List` |
| part | `NavigationMenu.Item` |
| part | `NavigationMenu.Trigger` |
| part | `NavigationMenu.Icon` |
| part | `NavigationMenu.Content` |
| part | `NavigationMenu.Link` |
| part | `NavigationMenu.Portal` |
| part | `NavigationMenu.Positioner` |
| part | `NavigationMenu.Popup` |
| part | `NavigationMenu.Viewport` |
| part | `NavigationMenu.Arrow` |