Navigation Menu
NavigationMenu renders semantic site or application navigation from an items array. Horizontal navigation uses flyout panels. Vertical navigation expands children inline and can switch to side flyouts when a containing sidebar collapses. Use Menu for commands.
Anatomy
#trigger: Custom top-level flyout trigger content.#link: Custom top-level direct-link content.#item: Custom flyout item or vertical row content.#item-leading: Icon or other content before a generated item label.#item-label: Generated item label replacement.#item-trailing: Action or metadata after a generated item label.#child-indicator: Expansion indicator for items with children.#[item.slot]: Per-item override for triggers or links.
Lists, item wrappers, links, disclosure triggers, inline content, and flyout viewports are generated by the component. Items with type: "label" or type: "separator" provide vertical grouping without requiring public sub-components.
When users move between flyout triggers, outgoing and incoming panels slide simultaneously according to activation direction while the viewport animates to its new dimensions. Initial open and final close retain the side-aware popup transition.
Usage
Examples
Selected item
Use the default v-model for the selected leaf. Selecting a new item updates its data-akaza-state="active" and aria-current, and clears the previous generated active state. A parent trigger receives data-akaza-active while one of its descendants is selected.
<NavigationMenu v-model="selected" :items="items" />
item.active remains useful for an initial route-driven state when no model value is set. For router integration, update the model from the current route.
Routes and actions
Use to for Vue Router or Nuxt routes and href for native links. A leaf with to renders RouterLink automatically when Vue Router is installed. Use as only when a custom link component is required.
const items = [
{
label: "Account",
to: "/account",
onClick: (event) => analytics.track("account-opened"),
},
{ label: "External docs", href: "https://example.com/docs" },
];
Resolution order is children, as, to, href, then button. onClick runs before selection and routing. Calling event.preventDefault() blocks navigation. Canceling the component's select event blocks both selection and navigation. onSelect runs only after selection is accepted.
Controlled open state
Bind v-model:open to observe or control the currently open flyout.
<script setup lang="ts">
import { ref } from "vue";
const open = ref<string | null>(null);
</script>
<template>
<NavigationMenu v-model:open="open" :items="items" />
</template>
Vertical navigation
Set orientation="vertical" to render nested children as inline disclosures. Expansion supports multiple branches and arbitrary nesting.
Collapsed sidebar
Pass the containing sidebar's collapsed slot value to Navigation Menu. In automatic mode, expanded vertical navigation uses inline children and collapsed navigation uses side flyouts.
<Sidebar collapsible="icon">
<template #default="{ collapsed }">
<NavigationMenu
v-model="selected"
orientation="vertical"
:collapsed="collapsed"
tooltip
:items="items"
aria-label="Workspace"
/>
</template>
</Sidebar>
Use content-mode="inline" or content-mode="flyout" to override automatic presentation. Collapsed vertical flyouts teleport to body by default so a scrollable sidebar cannot clip them.
Custom flyout items
Use #item for richer content while the component keeps generated list and link structure.
<template>
<NavigationMenu :items="items">
<template #item="{ item }">
<strong>{{ item.label }}</strong>
<small>{{ item.description }}</small>
</template>
</NavigationMenu>
</template>
API Reference
Models
| Model | Type | Default | Description |
|---|---|---|---|
v-model | string | null | defaultValue | Selected leaf value. Falls back to a string to, href, then label. |
v-model:open | string | null | null | Active horizontal or side flyout item. |
v-model:expanded | string[] | defaultExpanded and item defaults | Expanded inline item values. Multiple branches may remain open. |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | NavigationMenuItem[] | required | Top-level navigation items. |
defaultValue | string | null | null | Initially selected value when v-model is uncontrolled. |
orientation | "horizontal" | "vertical" | "horizontal" | Top-level layout and keyboard direction. |
contentMode | "auto" | "flyout" | "inline" | "auto" | Child presentation. Auto uses horizontal flyouts, vertical inline expansion, and collapsed vertical side flyouts. |
collapsed | boolean | false | Enables icon-rail behavior and automatic side flyouts for vertical navigation. |
tooltip | boolean | false | Shows accessible flyout labels for collapsed items without children. |
defaultExpanded | string[] | [] | Initially expanded inline item values. |
loop | boolean | true | Arrow-key focus wraps. |
dir | "ltr" | "rtl" | "ltr" | Horizontal direction and vertical flyout side. |
disabled | boolean | false | Disables trigger interaction. |
openDelay | number | 80 | Pointer-open delay in milliseconds. |
closeDelay | number | 150 | Pointer-close delay in milliseconds. |
sideOffset | number | 8 | Distance between a flyout and its trigger. |
teleport | string | false | automatic | Flyout Teleport target. Defaults to body for collapsed vertical navigation and no Teleport otherwise. |
ariaLabel | string | "Primary" | Accessible nav label. |
ui | NavigationMenuUi | — | Classes for structural parts. |
Emits
| Event | Payload | Description |
|---|---|---|
open-change | (value: string | null, details) | Fired before active flyout changes. |
expanded-change | (values: string[], details) | Fired before inline expansion changes. Details include item and expanded; call details.cancel() to reject it. |
value-change | (value, details) | Fired before the selected value changes. Details include item; call details.cancel() to reject it. |
select | (item, details) | Fired when a link/item is selected. |
Slots
| Slot | Props | Description |
|---|---|---|
trigger | NavigationMenuSlotProps | Top-level flyout trigger content. |
link | NavigationMenuSlotProps | Top-level direct-link content. |
item | NavigationMenuSlotProps | Flyout item or complete vertical row content. |
item-leading | NavigationMenuSlotProps | Leading icon/content for generated rows. |
item-label | NavigationMenuSlotProps | Generated label replacement. |
item-trailing | NavigationMenuSlotProps | Trailing action or metadata. |
child-indicator | NavigationMenuSlotProps | Expansion indicator for child-bearing items. |
[item.slot] | NavigationMenuSlotProps | Per-item complete-content override. |
NavigationMenuSlotProps exposes item, isOpen, isActive, depth, collapsed, and a native-handler-safe toggle action.
Item Shape
| Key | Type | Description |
|---|---|---|
value | string | Stable id. Falls back to a string to, href, then label. |
label | string | Visible label. |
type | "item" | "label" | "separator" | Vertical item, static group label, or separator. |
href | string | Native link target. Used when to is absent. |
to | unknown | Vue Router or Nuxt destination. Renders RouterLink unless as overrides it. |
as | string | Component | Explicit link component override. Takes precedence over to and href. |
icon | Component | Optional generated leading icon. Slots remain available for Iconify strings or custom markup. |
badge | string | number | Generated trailing badge. |
description | string | Optional flyout description. |
disabled | boolean | Disables the item. |
active | boolean | Fallback active state used while the selected model is null. |
defaultExpanded | boolean | Initially expands this inline branch. |
ariaCurrent | ARIA current value | Defaults to "page" when active. |
children | NavigationMenuItem[] | Flyout links. |
slot | string | Named per-item slot. |
onClick | (event: MouseEvent) => void | Runs first on leaf activation. May call preventDefault() to block navigation. |
onSelect | () => void | Runs after uncanceled selection and model update. |
UI Options
| Key | Description |
|---|---|
root | Root nav. |
list | Top-level list. |
item | Top-level item wrapper. |
trigger | Top-level item with flyout. |
link | Top-level direct link. |
indicator | Active flyout indicator. |
content | Flyout wrapper. |
viewport | Flyout viewport. |
panel | Active keyed panel inside the viewport. |
contentList | Flyout list. |
contentItem | Flyout item wrapper. |
contentLink | Flyout link. |
label | Flyout item label. |
description | Flyout item description. |
itemLeading | Generated item icon. |
itemLabel | Generated item label. |
itemTrailing | Generated trailing slot content. |
badge | Generated item badge. |
childIndicator | Child expansion indicator wrapper. |
inlineList | Nested inline list. |
inlineItem | Inline item wrapper. |
inlineTrigger | Inline disclosure trigger. |
inlineLink | Inline direct link. |
inlineContent | Animated inline disclosure wrapper. |
inlineContentInner | Overflow wrapper inside inline content. |
groupLabel | Static vertical group label. |
separator | Vertical separator. |
tooltip | Collapsed direct-item tooltip. |
Styling Hooks
| UI key | CSS class | Data attrs |
|---|---|---|
root | akaza-navigation-menu | data-akaza-state, data-akaza-disabled, data-akaza-orientation, data-akaza-content-mode, data-akaza-collapsed |
list | akaza-navigation-menu-list | — |
item | akaza-navigation-menu-item | data-akaza-state, data-akaza-active, data-akaza-disabled |
trigger | akaza-navigation-menu-trigger | data-akaza-state, data-akaza-active, data-akaza-disabled |
link | akaza-navigation-menu-link | data-akaza-state, data-akaza-active, data-akaza-disabled, aria-current |
indicator | akaza-navigation-menu-indicator | data-akaza-state |
content | akaza-navigation-menu-content | data-akaza-state, data-akaza-side, data-akaza-align, --akaza-navigation-menu-anchor-width, --akaza-navigation-menu-anchor-height, --akaza-navigation-menu-available-width, --akaza-navigation-menu-available-height, --akaza-navigation-menu-transform-origin, --akaza-navigation-menu-duration |
viewport | akaza-navigation-menu-viewport | data-akaza-activation-direction, --akaza-navigation-menu-viewport-width, --akaza-navigation-menu-viewport-height |
panel | akaza-navigation-menu-panel | data-akaza-state, data-akaza-motion="from-start|from-end|to-start|to-end", data-akaza-activation-direction="left|right" |
contentList | akaza-navigation-menu-content-list | — |
contentItem | akaza-navigation-menu-content-item | data-akaza-state, data-akaza-active, data-akaza-disabled |
contentLink | akaza-navigation-menu-content-link | data-akaza-state, data-akaza-active, aria-current |
label | akaza-navigation-menu-label | — |
description | akaza-navigation-menu-description | — |
itemLeading | akaza-navigation-menu-item-leading | — |
itemLabel | akaza-navigation-menu-item-label | — |
itemTrailing | akaza-navigation-menu-item-trailing | — |
badge | akaza-navigation-menu-badge | — |
childIndicator | akaza-navigation-menu-child-indicator | data-akaza-state |
inlineList | akaza-navigation-menu-inline-list | data-akaza-depth |
inlineItem | akaza-navigation-menu-inline-item | data-akaza-state, data-akaza-depth, data-akaza-disabled, data-akaza-active |
inlineTrigger | akaza-navigation-menu-inline-trigger | data-akaza-state, data-akaza-active, data-akaza-depth, data-akaza-value, data-akaza-disabled |
inlineLink | akaza-navigation-menu-inline-link | data-akaza-state, data-akaza-active, data-akaza-depth, data-akaza-value, data-akaza-disabled, aria-current |
inlineContent | akaza-navigation-menu-inline-content | data-akaza-state, data-akaza-parent-value |
inlineContentInner | akaza-navigation-menu-inline-content-inner | — |
groupLabel | akaza-navigation-menu-group-label | — |
separator | akaza-navigation-menu-separator | — |
tooltip | akaza-navigation-menu-tooltip | role="tooltip" |
Flyouts use side-aware transitions. Switching triggers animates both panels and resizes the viewport. Inline disclosure height uses --akaza-navigation-menu-inline-duration. Change flyout motion with --akaza-navigation-menu-duration, --akaza-navigation-menu-panel-duration, --akaza-navigation-menu-resize-duration, and --akaza-navigation-menu-slide-distance. Reduced-motion mode removes visible movement.
Keyboard
| Key | Behavior |
|---|---|
ArrowRight / ArrowLeft | Move between horizontal items. In vertical inline mode, expand/collapse a branch or return to its parent. In vertical flyout mode, open toward the reading direction. |
ArrowDown / ArrowUp | Move through vertical inline rows, vertical flyout triggers, or flyout links. |
ArrowDown / Enter / Space | Open a horizontal flyout item. Enter/Space also toggles inline disclosure buttons. |
Home / End | Focus first/last enabled top-level item. |
| Character keys | Typeahead across flyout triggers. |
ArrowDown / ArrowUp in flyout | Move through enabled flyout links. |
Escape | Close the active flyout. |