Components

Navigation Menu

Horizontal flyout and vertical application navigation from one items API.

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

ModelTypeDefaultDescription
v-modelstring | nulldefaultValueSelected leaf value. Falls back to a string to, href, then label.
v-model:openstring | nullnullActive horizontal or side flyout item.
v-model:expandedstring[]defaultExpanded and item defaultsExpanded inline item values. Multiple branches may remain open.

Props

PropTypeDefaultDescription
itemsNavigationMenuItem[]requiredTop-level navigation items.
defaultValuestring | nullnullInitially 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.
collapsedbooleanfalseEnables icon-rail behavior and automatic side flyouts for vertical navigation.
tooltipbooleanfalseShows accessible flyout labels for collapsed items without children.
defaultExpandedstring[][]Initially expanded inline item values.
loopbooleantrueArrow-key focus wraps.
dir"ltr" | "rtl""ltr"Horizontal direction and vertical flyout side.
disabledbooleanfalseDisables trigger interaction.
openDelaynumber80Pointer-open delay in milliseconds.
closeDelaynumber150Pointer-close delay in milliseconds.
sideOffsetnumber8Distance between a flyout and its trigger.
teleportstring | falseautomaticFlyout Teleport target. Defaults to body for collapsed vertical navigation and no Teleport otherwise.
ariaLabelstring"Primary"Accessible nav label.
uiNavigationMenuUiClasses for structural parts.

Emits

EventPayloadDescription
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

SlotPropsDescription
triggerNavigationMenuSlotPropsTop-level flyout trigger content.
linkNavigationMenuSlotPropsTop-level direct-link content.
itemNavigationMenuSlotPropsFlyout item or complete vertical row content.
item-leadingNavigationMenuSlotPropsLeading icon/content for generated rows.
item-labelNavigationMenuSlotPropsGenerated label replacement.
item-trailingNavigationMenuSlotPropsTrailing action or metadata.
child-indicatorNavigationMenuSlotPropsExpansion indicator for child-bearing items.
[item.slot]NavigationMenuSlotPropsPer-item complete-content override.

NavigationMenuSlotProps exposes item, isOpen, isActive, depth, collapsed, and a native-handler-safe toggle action.

Item Shape

KeyTypeDescription
valuestringStable id. Falls back to a string to, href, then label.
labelstringVisible label.
type"item" | "label" | "separator"Vertical item, static group label, or separator.
hrefstringNative link target. Used when to is absent.
tounknownVue Router or Nuxt destination. Renders RouterLink unless as overrides it.
asstring | ComponentExplicit link component override. Takes precedence over to and href.
iconComponentOptional generated leading icon. Slots remain available for Iconify strings or custom markup.
badgestring | numberGenerated trailing badge.
descriptionstringOptional flyout description.
disabledbooleanDisables the item.
activebooleanFallback active state used while the selected model is null.
defaultExpandedbooleanInitially expands this inline branch.
ariaCurrentARIA current valueDefaults to "page" when active.
childrenNavigationMenuItem[]Flyout links.
slotstringNamed per-item slot.
onClick(event: MouseEvent) => voidRuns first on leaf activation. May call preventDefault() to block navigation.
onSelect() => voidRuns after uncanceled selection and model update.

UI Options

KeyDescription
rootRoot nav.
listTop-level list.
itemTop-level item wrapper.
triggerTop-level item with flyout.
linkTop-level direct link.
indicatorActive flyout indicator.
contentFlyout wrapper.
viewportFlyout viewport.
panelActive keyed panel inside the viewport.
contentListFlyout list.
contentItemFlyout item wrapper.
contentLinkFlyout link.
labelFlyout item label.
descriptionFlyout item description.
itemLeadingGenerated item icon.
itemLabelGenerated item label.
itemTrailingGenerated trailing slot content.
badgeGenerated item badge.
childIndicatorChild expansion indicator wrapper.
inlineListNested inline list.
inlineItemInline item wrapper.
inlineTriggerInline disclosure trigger.
inlineLinkInline direct link.
inlineContentAnimated inline disclosure wrapper.
inlineContentInnerOverflow wrapper inside inline content.
groupLabelStatic vertical group label.
separatorVertical separator.
tooltipCollapsed direct-item tooltip.

Styling Hooks

UI keyCSS classData attrs
rootakaza-navigation-menudata-akaza-state, data-akaza-disabled, data-akaza-orientation, data-akaza-content-mode, data-akaza-collapsed
listakaza-navigation-menu-list
itemakaza-navigation-menu-itemdata-akaza-state, data-akaza-active, data-akaza-disabled
triggerakaza-navigation-menu-triggerdata-akaza-state, data-akaza-active, data-akaza-disabled
linkakaza-navigation-menu-linkdata-akaza-state, data-akaza-active, data-akaza-disabled, aria-current
indicatorakaza-navigation-menu-indicatordata-akaza-state
contentakaza-navigation-menu-contentdata-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
viewportakaza-navigation-menu-viewportdata-akaza-activation-direction, --akaza-navigation-menu-viewport-width, --akaza-navigation-menu-viewport-height
panelakaza-navigation-menu-paneldata-akaza-state, data-akaza-motion="from-start|from-end|to-start|to-end", data-akaza-activation-direction="left|right"
contentListakaza-navigation-menu-content-list
contentItemakaza-navigation-menu-content-itemdata-akaza-state, data-akaza-active, data-akaza-disabled
contentLinkakaza-navigation-menu-content-linkdata-akaza-state, data-akaza-active, aria-current
labelakaza-navigation-menu-label
descriptionakaza-navigation-menu-description
itemLeadingakaza-navigation-menu-item-leading
itemLabelakaza-navigation-menu-item-label
itemTrailingakaza-navigation-menu-item-trailing
badgeakaza-navigation-menu-badge
childIndicatorakaza-navigation-menu-child-indicatordata-akaza-state
inlineListakaza-navigation-menu-inline-listdata-akaza-depth
inlineItemakaza-navigation-menu-inline-itemdata-akaza-state, data-akaza-depth, data-akaza-disabled, data-akaza-active
inlineTriggerakaza-navigation-menu-inline-triggerdata-akaza-state, data-akaza-active, data-akaza-depth, data-akaza-value, data-akaza-disabled
inlineLinkakaza-navigation-menu-inline-linkdata-akaza-state, data-akaza-active, data-akaza-depth, data-akaza-value, data-akaza-disabled, aria-current
inlineContentakaza-navigation-menu-inline-contentdata-akaza-state, data-akaza-parent-value
inlineContentInnerakaza-navigation-menu-inline-content-inner
groupLabelakaza-navigation-menu-group-label
separatorakaza-navigation-menu-separator
tooltipakaza-navigation-menu-tooltiprole="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

KeyBehavior
ArrowRight / ArrowLeftMove 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 / ArrowUpMove through vertical inline rows, vertical flyout triggers, or flyout links.
ArrowDown / Enter / SpaceOpen a horizontal flyout item. Enter/Space also toggles inline disclosure buttons.
Home / EndFocus first/last enabled top-level item.
Character keysTypeahead across flyout triggers.
ArrowDown / ArrowUp in flyoutMove through enabled flyout links.
EscapeClose the active flyout.