# NavigationMenu
Site navigation with large animated dropdown panels.
```ehtml Example
import {
NavigationMenu, NavigationMenuItem, NavigationMenuLink, navigationMenuTriggerClass,
} from "@elements/ui/navigation-menu";
Introduction
Installation
...
Docs
```
## Parts
| Part | What it is |
|---|---|
| `NavigationMenu` | The root ``: owns value (the open item), renders the list, the optional indicator and the shared viewport. |
| `NavigationMenuItem` | A list item. With label it is a trigger button and a panel (its default slot); without, it holds a link. |
| `NavigationMenuLink` | A link. Choosing it closes the menu. active marks the current page (aria-current=page). trigger gives it the trigger look for the top list. |
| `NavigationMenu sub` | A NavigationMenu with sub inside a panel is a submenu: one item always open, panels inline, switching on hover or click. |
| `.navigation-menu-viewport` | The box under the open panel; it animates between panels' sizes (--navigation-menu-viewport-width and -height). |
| `.navigation-menu-indicator` | The arrow under the open trigger, moved with --navigation-menu-indicator-translate-x (or -y) and sized with --navigation-menu-indicator-size. |
## Attributes
### NavigationMenu
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | `string` (two-way) | `""` | The open item's value; empty when closed. Bind it to open an item from code. |
| `delay` | `number` | `200` | Hover time in ms before a panel opens. |
| `skipDelay` | `number` | `300` | Within this many ms of a close, hovering opens at once, so moving across triggers does not wait each time. |
| `closeDelay` | `number` | `150` | Ms after the pointer leaves the trigger and panel before the panel closes. |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Horizontal opens panels below; vertical stacks the list and opens panels beside it. |
| `viewport` | `boolean` | `true` | Show panels in one shared, animated box under the list. false places each panel under its own trigger with its own box. |
| `indicator` | `boolean` | `false` | Show an arrow under the open trigger. |
| `arrow` | `boolean` | `false` | Draw an arrow on the viewport's edge that points at the open trigger. |
| `arrowPadding` | `number` | `5` | px the viewport arrow keeps from the viewport's corners. |
| `sub` | `boolean` | `false` | This menu is a submenu inside a panel: one item is always open and its panel shows inline. |
| `align` | `"start" \| "center" \| "end"` | `"start"` | Where the viewport (or a panel) sits along the list. |
| `sideOffset` | `number` | `6` | Gap between the list and the viewport, in px. |
| `alignOffset` | `number` | `0` | Moves the viewport (or a panel) along the list from its aligned spot, in px. |
| `positionMethod` | `"fixed" \| "absolute"` | `"fixed"` | "absolute" places the viewport in page coordinates instead of viewport ones. |
| `disableAnchorTracking` | `boolean` | `false` | Place the viewport once when it opens; it stays put if its anchor moves, and is placed again on a scroll or resize. |
| `collisionBoundary` | `string` | `""` | A CSS selector for boxes whose edges count like the screen's when placing the viewport. |
| `sticky` | `"partial" \| "always"` | `"partial"` | always keeps the viewport in view when the list scrolls away; otherwise it hides with data-anchor-hidden. |
| `anchor` | `string \| Element \| null` | `null` | An element, or a selector for one, the viewport is placed against instead of the list, such as a whole header. |
| `collisionPadding` | `number` | `8` | px the viewport keeps from the screen's edges and the collision boundary. |
| `collisionAvoidance` | `{ side?: "flip" \| "shift" \| "none"; align?: "flip" \| "shift" \| "none"; fallbackAxisSide?: "start" \| "end" \| "none" } \| null` | `null` | How the viewport avoids the edges. By default it keeps its side and slides along it; side "flip" opens it above the list when there is no room below. |
| `backdrop` | `boolean` | `false` | Render a layer under the open panel that dims the page, cut away over the list; a press on it closes the menu. |
| `dir` | `"" \| "ltr" \| "rtl"` | `""` | Reading direction for the arrow keys. Empty follows the page. |
| `label` | `string` | `"Main"` | aria-label of the `` landmark. |
| `class` | `string` | `""` | Extra classes on the ``. |
| `onValueChange` | `(value: string) => void` | `() => {}` | Called when the menu opens, switches or closes a panel itself. |
| `onOpenChangeComplete` | `(open: boolean) => void` | `() => {}` | Called once a panel has finished opening from a closed menu (true), and once the last panel and the viewport have finished closing (false). |
| `onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside` | `(e) => void` | `() => {}` | Called before the open panel closes that way; e.preventDefault() keeps it open. |
### NavigationMenuItem
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | `string` | `an id` | Names the item for the root's value. |
| `label` | `string` | `""` | Makes the item a trigger with this text and its default slot a panel. The trigger slot replaces the text. |
| `disabled` | `boolean` | `false` | The trigger does not open its panel. |
| `keepMounted` | `boolean` | `false` | The panel renders with the page and stays in the DOM, hidden, while closed, so its links are there for crawlers. |
| `class` | `string` | `""` | Extra classes on the panel. |
| `attrs` | `Record` | `{}` | Other attributes for the trigger button. |
### NavigationMenuLink
| Attribute | Type | Default | Description |
|---|---|---|---|
| `href` | `string` | (required) | Required. Where the link goes. |
| `active` | `boolean` | `false` | The current page: aria-current=page and data-active. |
| `trigger` | `boolean` | `false` | Style the link like a trigger, for a link in the top list. |
| `closeOnClick` | `boolean` | `true` | false follows the link and leaves the menu open. |
| `onSelect` | `(e: Event) => void` | `() => {}` | Called when the link is chosen; e.preventDefault() keeps the menu open and cancels the navigation. |
| `class, attrs` | `string, Record` | `"", {}` | Extra classes and attributes on the ``. |
## Slots
| Slot | Part | Content |
|---|---|---|
| `default` | `NavigationMenu` | The NavigationMenuItem elements. |
| `default` | `NavigationMenuItem` | With label: the panel's content. Without: the item's link. |
| `trigger` | `NavigationMenuItem` | Rich trigger content; label is still needed (it makes the item a trigger). |
| `default` | `NavigationMenuLink` | The link's content. |
## Keyboard
| Keys | Action |
|---|---|
| `Tab / Shift + Tab` | Moves through triggers, links and an open panel's links in page order. |
| `Enter / Space` | On a trigger: opens or closes its panel. |
| `ArrowRight / ArrowLeft` | The next or previous trigger or link in the list (flipped under rtl). |
| `ArrowDown / ArrowUp` | The next or previous trigger or link, in either orientation, unless ArrowDown enters an open panel. |
| `ArrowDown (horizontal), ArrowRight (vertical)` | On an open trigger: moves into its panel. |
| `Home / End` | The first or last trigger or link in the list. |
| `Arrow keys in a panel` | The next or previous link or control in the panel. |
| `Escape` | Closes the panel and focuses its trigger. |
## Data attributes
| Attribute | Values | On | Description |
|---|---|---|---|
| `data-orientation` | `"horizontal" \| "vertical"` | nav, list, indicator, viewport | |
| `data-state` | `"open" \| "closed"` | trigger, panel, viewport | |
| `data-pressed` | present | trigger | While the panel a click of the trigger opened is open (not a hover). |
| `data-instant` | `"click" \| "dismiss"` | viewport, panel | click when a keyboard press opened it, dismiss when Escape closed it. |
| `data-side, data-align` | placement | viewport, panel, arrow | |
| `data-uncentered` | present | arrow | When the corners hold the arrow off the trigger's center. |
| `data-anchor-hidden` | present | viewport, panel | While the list is scrolled out of view (unless sticky is always). |
| `--positioner-width / --positioner-height` | px | viewport | Its own size while open. |
| `data-state, data-starting-style, data-ending-style` | `"open" \| "closed"` | .navigation-menu-backdrop | With backdrop. |
| `data-disabled` | present | trigger | |
| `data-motion` | `"from-start" \| "from-end" \| "to-start" \| "to-end"` | panel | Which way a panel enters or leaves when the open item changes. |
| `data-state` | `"visible" \| "hidden"` | indicator | |
| `data-active` | present | NavigationMenuLink | The current page. |
## Accessibility
- A `` landmark (aria-label, default Main) with a list of triggers and links: not role=menu, since site navigation is a set of disclosures (WAI-ARIA disclosure navigation).
- Each trigger is a `` with aria-expanded and aria-controls; its panel follows it in the DOM, so Tab reaches the panel's links right after the trigger.
- Escape closes the panel and returns focus to its trigger; focus or a press outside the navigation closes it.
- NavigationMenuLink active sets aria-current=page.
- Panels are popover=manual in the top layer: never clipped, no portal.
## See also
- [DropdownMenu](dropdown-menu): A menu of actions from a button, with submenus, checkbox and radio items.
- [ContextMenu](context-menu): A menu at the pointer on right-click or long-press.
- [Menubar](menubar): A desktop-style bar of menus that stays open as you move across it.