Navigation Menu
A collection of links and menus for website navigation.
Anatomy
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger />
<NavigationMenu.Content>
<NavigationMenu.Link />
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Indicator>
<NavigationMenu.Arrow />
</NavigationMenu.Indicator>
</NavigationMenu.List>
<NavigationMenu.ViewportPositioner>
<NavigationMenu.Viewport />
</NavigationMenu.ViewportPositioner>
</NavigationMenu.Root>
Examples
Viewport
Render NavigationMenu.Viewport to share one animated panel across menu items. The viewport resizes as you move between
triggers.
Current link
Pass the current prop to the link that represents the page the user is on. It renders aria-current="page" for
assistive technology and a data-current attribute for styling.
Vertical
Set orientation="vertical" on the root to build sidebar-style navigation. Panels open to the side, and the keyboard
model adapts: ArrowUp and ArrowDown move between triggers, ArrowRight enters the open panel.
Controlled
Use the value and onValueChange props to control the active menu item.
Root Provider
An alternative way to control the navigation menu is to use the RootProvider component and the useNavigationMenu
hook. This way you can access the state and methods from outside the component.
If you're using the
RootProvidercomponent, you don't need to use theRootcomponent.
Context
Access the navigation menu's state with NavigationMenu.Context or the useNavigationMenuContext hook:
Guides
Custom links
Use the asChild prop to render NavigationMenu.Link as your framework's link component for client-side routing.
import { Link as RouterLink } from 'react-router-dom'
import { NavigationMenu } from '@ark-ui/<framework>/navigation-menu'
export const MenuLink = (props: NavigationMenu.LinkProps) => {
return (
<NavigationMenu.Link {...props} asChild>
<RouterLink to={props.href ?? '#'}>{props.children}</RouterLink>
</NavigationMenu.Link>
)
}
Viewport size
The following CSS variables are exposed on NavigationMenu.Root and NavigationMenu.Viewport:
/* size and position of the active trigger */
--trigger-width: <pixel-value>;
--trigger-height: <pixel-value>;
--trigger-x: <pixel-value>;
--trigger-y: <pixel-value>;
/* size and position of the active content */
--viewport-width: <pixel-value>;
--viewport-height: <pixel-value>;
--viewport-x: <pixel-value>;
--viewport-y: <pixel-value>;
Use --viewport-width and --viewport-height to animate the shared panel as the active item changes:
[data-scope='navigation-menu'][data-part='viewport'] {
width: var(--viewport-width);
height: var(--viewport-height);
transition:
width 250ms ease,
height 250ms ease;
}
Large menus
When menu content is taller than the viewport, constrain the panel and scroll the content:
[data-scope='navigation-menu'][data-part='viewport'] {
max-height: min(var(--viewport-height), 70vh);
}
[data-scope='navigation-menu'][data-part='content'] {
max-height: 70vh;
overflow-y: auto;
}
API Reference
Props
Root
Renders a <> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeDelay | 300 | numberThe delay before the menu closes |
defaultValue | stringThe default value of the navigation menu. Use when you don't want to control the value of the menu. | |
disableClickTrigger | booleanWhether to disable the click trigger | |
disableHoverTrigger | booleanWhether to disable the hover trigger | |
disablePointerLeaveClose | booleanWhether to disable the pointer leave close | |
hideMode | 'display-none' | HideModeHow to hide content when mounted but not present. - `'display-none'`: HTML `hidden` attribute. Effects stay alive. - `'activity'`: React 19 `<Activity mode="hidden">`. Effects pause. Requires React 19+. |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
list: string
item: string
trigger: (value: string) => string
content: (value: string) => string
viewport: string
}>The ids of the elements in the machine. | |
lazyMount | false | booleanWhether to enable lazy mounting |
onValueChange | (details: ValueChangeDetails) => voidFunction called when the value of the menu changes | |
openDelay | 200 | numberThe delay before the menu opens |
orientation | 'horizontal' | 'horizontal' | 'vertical'The orientation of the element. |
translations | IntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states | |
unmountOnExit | false | booleanWhether to unmount on exit. |
value | stringThe controlled value of the navigation menu |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | root |
[data-orientation] | The orientation of the navigation-menu |
| CSS Variable | Description |
|---|---|
--trigger-width | The width of the Root |
--trigger-height | The height of the Root |
--trigger-x | The trigger x value for the Root |
--trigger-y | The trigger y value for the Root |
--viewport-width | The width of the Root |
--viewport-height | The height of the Root |
--viewport-x | The viewport x value for the Root |
--viewport-y | The viewport y value for the Root |
Arrow
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | arrow |
[data-orientation] | The orientation of the arrow |
Content
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
value | stringThe value of the item this content belongs to |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | content |
[data-state] | "open" | "closed" |
[data-orientation] | The orientation of the content |
[data-value] | The value of the item |
| CSS Variable | Description |
|---|---|
--layer-index | The index of the dismissable in the layer stack |
--nested-layer-count | The number of nested navigation-menus |
Indicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | indicator |
[data-state] | "open" | "closed" |
[data-orientation] | The orientation of the indicator |
ItemIndicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | item-indicator |
[data-state] | "open" | "closed" |
[data-orientation] | The orientation of the item |
[data-value] | The value of the item |
Item
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
value | stringThe value of the item | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | booleanWhether the item is disabled |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | item |
[data-value] | The value of the item |
[data-state] | "open" | "closed" |
[data-orientation] | The orientation of the item |
[data-disabled] | Present when disabled |
Link
Renders a <a> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeOnClick | true | booleanWhether to close the navigation menu when the link is clicked. |
current | booleanWhether the link is the current link | |
onSelect | (event: CustomEvent<any>) => voidFunction called when the link is selected | |
value | stringThe value of the item this link belongs to |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | link |
[data-value] | The value of the item |
[data-current] | Present when current |
List
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | list |
[data-orientation] | The orientation of the list |
RootProvider
Renders a <> element.
| Prop | Default | Type |
|---|---|---|
value | UseNavigationMenuReturn | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
hideMode | 'display-none' | HideModeHow to hide content when mounted but not present. - `'display-none'`: HTML `hidden` attribute. Effects stay alive. - `'activity'`: React 19 `<Activity mode="hidden">`. Effects pause. Requires React 19+. |
lazyMount | false | booleanWhether to enable lazy mounting |
unmountOnExit | false | booleanWhether to unmount on exit. |
Trigger
Renders a <button> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | booleanWhether the item is disabled |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | trigger |
[data-trigger-proxy-id] | |
[data-value] | The value of the item |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
ViewportPositioner
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
align | 'center' | 'start' | 'end'Placement of the viewport for css variables `(--viewport-x, --viewport-y)`. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | viewport-positioner |
[data-orientation] | The orientation of the viewportpositioner |
[data-align] |
Viewport
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | navigation-menu |
[data-part] | viewport |
[data-state] | "open" | "closed" |
[data-orientation] | The orientation of the viewport |
[data-align] |
| CSS Variable | Description |
|---|---|
--viewport-width | The width of the Viewport |
--viewport-height | The height of the Viewport |
--viewport-x | The viewport x value for the Viewport |
--viewport-y | The viewport y value for the Viewport |
Context
API
| Property | Type |
|---|---|
value | string | nullThe current value of the menu |
setValue | (value: string) => voidSets the value of the menu |
open | booleanWhether the menu is open |
isViewportRendered | booleanWhether the viewport is rendered |
getViewportNode | () => HTMLElement | nullGets the viewport node element |
orientation | OrientationThe orientation of the menu |
reposition | VoidFunctionFunction to reposition the viewport |
Accessibility
Complies with the Navigation Menubar WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
ArrowDown | When focus is on trigger (vertical orientation), moves focus to the next trigger. |
ArrowUp | When focus is on trigger (vertical orientation), moves focus to the previous trigger. |
ArrowRight | When focus is on trigger (horizontal orientation), moves focus to the next trigger. When focus is on content, moves focus to the next link. |
ArrowLeft | When focus is on trigger (horizontal orientation), moves focus to the previous trigger. When focus is on content, moves focus to the previous link. |
Home | When focus is on trigger, moves focus to the first trigger. When focus is on content, moves focus to the first link. |
End | When focus is on trigger, moves focus to the last trigger. When focus is on content, moves focus to the last link. |