Accessible, unstyled site navigation with hover-intent flyouts, an indicator, and a measured viewport.
|
|
| Package |
@vizejs/ui/navigation-menu |
| Maturity |
stable |
| Own the source |
vize lib pull navigation-menu |
| Requires |
collection, context, controllable-state, id |
| Aliases |
site navigation, mega menu, navbar, flyout navigation, disclosure navigation |
| Covers |
WAI-ARIA disclosure navigation pattern, Radix Navigation Menu, Reka UI Navigation Menu, Ark UI Navigation Menu |
Usage
import { NavigationMenu, NavigationMenuRoot, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport } from "@vizejs/ui/navigation-menu";
Or copy the source into your project with vize lib pull navigation-menu (see Source Distribution).
API
Source: src/families/navigation/navigation-menu/navigation-menu-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
modelValue |
NavigationMenuValue |
undefined |
Controlled open item value (v-model). undefined selects uncontrolled behavior. |
defaultValue |
NavigationMenuValue |
null |
Initially open item value for uncontrolled use. |
delayDuration |
number |
200 |
Hover time in milliseconds before a pointer opens a flyout. |
skipDelayDuration |
number |
300 |
Window in milliseconds after closing during which hovering another trigger opens instantly. |
closeDelay |
number |
150 |
Grace time in milliseconds before a pointer leaving the trigger or flyout closes it. |
orientation |
NavigationMenuOrientation |
"horizontal" |
Layout axis of the top-level list, used for arrow keys and the open key. |
dir |
NavigationMenuDirection |
undefined |
Reading direction for horizontal arrow keys and motion attributes. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
ariaLabel |
string |
undefined |
Accessible name of the navigation landmark. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the landmark. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: NavigationMenuValue] |
Fired with the next open item value whenever a flyout opens or closes. |
change |
[ value: NavigationMenuValue, previous: NavigationMenuValue, reason: NavigationMenuChangeReason, ] |
Fired after a distinct open-value change with the input that caused it. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuSlotState |
List, item, and viewport children. Receives the open value and axis. |
Exposed
| Member |
Type |
Description |
close |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
open |
— |
|
value |
— |
|
Source: src/families/navigation/navigation-menu/navigation-menu-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned base id. null and undefined select a deterministic fallback. |
modelValue |
NavigationMenuValue |
undefined |
Controlled open item value (v-model). undefined selects uncontrolled behavior. |
defaultValue |
NavigationMenuValue |
null |
Initially open item value for uncontrolled use. |
delayDuration |
number |
200 |
Hover time in milliseconds before a pointer opens a flyout. |
skipDelayDuration |
number |
300 |
Window in milliseconds after closing during which hovering another trigger opens instantly. |
closeDelay |
number |
150 |
Grace time in milliseconds before a pointer leaving the trigger or flyout closes it. |
orientation |
NavigationMenuOrientation |
"horizontal" |
Layout axis of the top-level list, used for arrow keys and the open key. |
dir |
NavigationMenuDirection |
undefined |
Reading direction for horizontal arrow keys and motion attributes. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
ariaLabel |
string |
undefined |
Accessible name of the navigation landmark. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the landmark. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: NavigationMenuValue] |
Fired with the next open item value whenever a flyout opens or closes. |
change |
[ value: NavigationMenuValue, previous: NavigationMenuValue, reason: NavigationMenuChangeReason, ] |
Fired after a distinct open-value change with the input that caused it. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuSlotState |
List, item, and viewport children. Receives the open value and axis. |
Exposed
| Member |
Type |
Description |
element |
HTMLElement | null |
Rendered navigation landmark. |
value |
NavigationMenuValue |
Open item value. |
open |
(value: string) => boolean |
Open one item's flyout immediately. |
close |
() => boolean |
Close the open flyout immediately. |
Source: src/families/navigation/navigation-menu/navigation-menu-content.vue
Props
| Prop |
Type |
Default |
Description |
forceMount |
boolean |
false |
Keep closed flyout content rendered (inside the hidden container) for exit animations or crawlable links. Without it, closed flyouts keep an empty hidden container. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuItemSlotState |
Flyout content, usually NavigationMenuLink lists. Receives the open state. |
Source: src/families/navigation/navigation-menu/navigation-menu-indicator.vue
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuMeasuredSlotState |
Optional indicator content such as an arrow. Receives the open value. |
Source: src/families/navigation/navigation-menu/navigation-menu-item.vue
Props
| Prop |
Type |
Default |
Description |
value (required) |
string |
required |
Stable item value used as the open value of its flyout. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuItemSlotState |
Trigger, content, or a plain link. Receives the open state of this item. |
Source: src/families/navigation/navigation-menu/navigation-menu-link.vue
Props
| Prop |
Type |
Default |
Description |
as |
PrimitiveAs |
"a" |
Native element, custom element, or router component to render. |
href |
string |
undefined |
Native link destination. Router components can receive their own route attrs instead. |
active |
boolean |
false |
Whether the link represents the current page (aria-current="page"). |
Events
| Event |
Payload |
Description |
select |
[nativeEvent: MouseEvent] |
Fired when the link is activated. Call preventDefault() to keep the flyout open. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuLinkSlotState |
Link content. Receives whether it represents the current page. |
Source: src/families/navigation/navigation-menu/navigation-menu-list.vue
Slots
| Slot |
Slot props |
Description |
default |
{ /** Layout axis of the list. */ readonly orientation: NavigationMenuOrientation; } |
NavigationMenuItem children. Receives the list axis. |
Source: src/families/navigation/navigation-menu/navigation-menu-trigger.vue
Props
| Prop |
Type |
Default |
Description |
disabled |
boolean |
false |
Disable the trigger and its flyout. |
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuItemSlotState |
Trigger label. Receives the open state of the owning item. |
Source: src/families/navigation/navigation-menu/navigation-menu-viewport.vue
Slots
| Slot |
Slot props |
Description |
default |
NavigationMenuMeasuredSlotState |
Optional backdrop content. Receives the open value. |
Behavior
Normative state x input -> outcome table for the @vizejs/ui/navigation-menu
parts: navigation-menu-root.vue, navigation-menu-list.vue,
navigation-menu-item.vue, navigation-menu-trigger.vue,
navigation-menu-content.vue, navigation-menu-link.vue,
navigation-menu-indicator.vue, and navigation-menu-viewport.vue. Every row
is proven by the named test in navigation-menu.test.ts or
navigation-menu-ssr.test.ts; compile-only guarantees live in
navigation-menu.types.test-d.ts.
The menu follows the APG disclosure navigation pattern (not role="menu"): a
labelled <nav> with a <ul> of items, native <button aria-expanded aria-controls> triggers, and flyouts rendered inline after their trigger so
the native tab order reaches them. The viewport is a measured backdrop that
publishes --vize-navigation-menu-viewport-width/height; the indicator
publishes --vize-navigation-menu-indicator-offset/size. Both are measured on
the client only.
| ID |
State |
Input |
Outcome |
Evidence |
| N1 |
closed |
render |
labelled nav, deterministic trigger/content ids, closed flyouts unmounted, aria-current links |
renders a labelled disclosure navigation with wired triggers and closed flyouts |
| N2 |
any |
trigger click |
toggles the flyout inline after the trigger and reports toggle |
click toggles a flyout inline after its trigger |
| N3 |
mouse or pen |
hover, move, leave, re-enter |
opens after delayDuration, switches instantly, closes after closeDelay, skip window reopens |
hover opens after the delay, skips it between triggers, and closes after a grace period |
| N4 |
touch |
pointerenter |
hover intent is ignored; touch uses click |
touch pointers never open on hover |
| N5 |
focus on a list entry |
arrows, Home, End, open key |
roving between triggers and top-level links (wrapping); ArrowDown opens and focuses the flyout |
arrow keys move between top-level entries and the open key enters the flyout |
| N6 |
open |
Escape, outside pointer, focus out, link |
dismisses; Escape restores focus to the trigger; flyout links close with reason link |
Escape, outside pointerdown, focus leaving, and link selection dismiss the flyout |
| N7 |
switching items |
open another item, forceMount |
data-motion reports from/to start/end; force-mounted flyouts stay hidden while closed |
motion attributes follow the direction between items and forceMount keeps hidden flyouts |
| N8 |
controlled / exposed root |
click, setProps, open/close |
the parent owns the open value; imperative open/close report distinct changes |
controlled values wait for the parent and the root exposes open/close |
| N9 |
open |
measure |
indicator and viewport publish CSS variables for the open item and clear them when closed |
the indicator and viewport publish geometry for the open item |
| N10 |
disabled trigger |
click, hover, open key |
the flyout never opens |
disabled triggers ignore click, hover, and the open key |
| N11 |
missing provider |
setup |
parts fail closed with the shared context diagnostic |
compound parts require matching providers |
| N12 |
SSR and hydration |
isolated render/mount |
default-open flyouts render, geometry is omitted, hydration has no warnings |
navigation-menu-ssr.test.ts |
| N13 |
link href / as |
render |
script-capable hrefs are dropped; as renders router or custom elements |
links drop script-capable hrefs and render custom elements |