Navigation Menu
A row of triggers and links that leads users to the sections of an application.
A navigation menu lists the sections of an application in a row. A trigger opens the links of its section in a popup when users rest the mouse pointer on it or press it, and a link in the row leads to its page directly. All triggers share one popup, which NavigationMenu renders itself. The popup moves to the active trigger and takes the size of its content, so the examples set a width on the list of links. Users move through the row with the left and right arrow keys and open the popup of a trigger with the down arrow key. The popup closes when users press Escape, press outside of it or move the focus out of the navigation menu. A popup that opened under the resting pointer also closes when the pointer leaves the trigger and the popup.
Usage
Examples
Top-Level Link
Some sections consist of a single page, such as the daily overview of a store, and a popup with one entry would only add a step. Placed directly in an item, without a trigger, a link takes users to that page with a single click.
With Icon
Users who return to the same pages every day learn to find them by shape before they read a word. An icon inside a link supports that recognition, while the name of the page keeps the meaning clear for users who see the icon for the first time.
Active Link
Orientation matters most deep inside an application, where many pages resemble each other. Marked with active, a link shows the page that users are on, visibly and for assistive technology, so they recognize their position as soon as they open its section.
Close on Click
Applications that switch pages without a full reload keep the navigation menu in place, so a popup that stays open would cover part of the page that users just opened. With closeOnClick on a link, the popup closes as soon as users choose that link, and the new page appears unobstructed.
Disabled Trigger
Now and then a section is unavailable, for example because users lack the rights for it. Set on its trigger, disabled keeps the popup of that section closed, yet the trigger stays focusable, so users who move through the navigation with the keyboard still learn that the section exists.
Open by Default
A start page often exists to send users onward to their daily work. Through defaultValue, the popup of one section is already open at first render, and from then on users move to another section or close the popup as usual.
Controlled
Sometimes the application decides which section is open, for example when a notice on the page guides users to the section where their next task waits. With value and onValueChange, the application holds the open item itself, so any part of the interface can open a section or close the popup.
API Reference
NavigationMenu
| Prop | value |
|---|---|
| Type | any |
| Default | – |
| Description | Sets the value of the item whose popup is open and makes the navigation menu controlled. With null, the popup is closed. Update it in onValueChange. |
| Prop | defaultValue |
|---|---|
| Type | any |
| Default | null |
| Description | Sets the value of the item whose popup is open at first render. The navigation menu then tracks the open item itself. |
| Prop | onValueChange |
|---|---|
| Type | (value: any, eventDetails: NavigationMenuRootChangeEventDetails) => void |
| Default | – |
| Description | Runs when users open the popup of an item, move to another item or close the popup. It receives the value of the item that is open afterwards, or null when the popup closes. |
| Prop | onOpenChangeComplete |
|---|---|
| Type | (open: boolean) => void |
| Default | – |
| Description | Runs after the popup has closed and its animations have finished. It receives false. |
| Prop | actionsRef |
|---|---|
| Type | RefObject<NavigationMenuRootActions | null> |
| Default | – |
| Description | Receives the function unmount, which removes the closed popup from the DOM. With actionsRef, the navigation menu no longer removes the popup itself, so code that controls the closing animation calls unmount when the animation has finished. |
| Prop | delay |
|---|---|
| Type | number |
| Default | 50 |
| Description | Sets how many milliseconds the pointer must rest on a trigger before the popup opens. While the popup is open, the pointer moves it to another trigger without this delay. |
| Prop | closeDelay |
|---|---|
| Type | number |
| Default | 50 |
| Description | Sets how many milliseconds the popup stays open after the pointer has left the trigger and the popup. |
| Prop | orientation |
|---|---|
| Type | "horizontal" | "vertical" |
| Default | "horizontal" |
| Description | Sets the arrow keys that move through the triggers and links of the list: left and right for "horizontal", up and down for "vertical". The key that opens a popup follows it: the down arrow for "horizontal", and for "vertical" the right arrow, or the left arrow in a right-to-left layout. It doesn't change the layout of the items. |
| Prop | align |
|---|---|
| Type | "start" | "center" | "end" |
| Default | "start" |
| Description | Sets where the popup lines up with the active trigger: at its start, its center or its end. NavigationMenu passes it to the NavigationMenuPositioner that it renders after its children. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the navigation menu with another component. |
NavigationMenuList
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the list with another component. |
NavigationMenuItem
| Prop | value |
|---|---|
| Type | any |
| Default | – |
| Description | Identifies the item in value and defaultValue of the navigation menu. Without it, the item gets a generated ID. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the item with another component. |
NavigationMenuTrigger
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the trigger with another component. |
| Prop | nativeButton |
|---|---|
| Type | boolean |
| Default | true |
| Description | Declares whether the rendered element is a native button. Set it to false when render returns a different element. |
| Prop | disabled |
|---|---|
| Type | boolean |
| Default | false |
| Description | Prevents users from opening the popup of the item with this trigger. The trigger stays focusable. |
NavigationMenuContent
| Prop | keepMounted |
|---|---|
| Type | boolean |
| Default | false |
| Description | Keeps the content in the DOM while the popup of its item is closed. The page that the server renders then contains the content, so web crawlers find its links. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the content with another component. |
NavigationMenuLink
| Prop | href |
|---|---|
| Type | string |
| Default | – |
| Description | Sets the address of the page that the link opens. Leave it out when render supplies an element that carries its own address. |
| Prop | active |
|---|---|
| Type | boolean |
| Default | false |
| Description | Marks the link as the page that users are on. It highlights the link and reports the current page to assistive technology. |
| Prop | closeOnClick |
|---|---|
| Type | boolean |
| Default | false |
| Description | Closes the popup when users click the link. Without it, a click leaves the popup open. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the link with another component. |
NavigationMenuIndicator
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the indicator with another component. |
NavigationMenuPositioner
| Prop | side |
|---|---|
| Type | "top" | "bottom" | "left" | "right" | "inline-end" | "inline-start" |
| Default | "bottom" |
| Description | Sets the side of the active trigger that the popup opens on. "inline-start" and "inline-end" follow the reading direction. The popup moves to the opposite side when the chosen one has too little space. |
| Prop | sideOffset |
|---|---|
| Type | number | OffsetFunction |
| Default | 8 |
| Description | Sets the distance between the active trigger and the popup in pixels. A function receives the side, the alignment and the dimensions of the trigger and the positioner, and returns the distance. |
| Prop | align |
|---|---|
| Type | "start" | "center" | "end" |
| Default | "start" |
| Description | Sets where the popup lines up with the active trigger along the chosen side: at its start, its center or its end. |
| Prop | alignOffset |
|---|---|
| Type | number | OffsetFunction |
| Default | 0 |
| Description | Moves the popup along the alignment axis by a number of pixels. A function receives the same data as the one for sideOffset and returns the offset. |
| Prop | anchor |
|---|---|
| Type | Element | VirtualElement | RefObject<Element | null> | (() => Element | VirtualElement | null) | null |
| Default | – |
| Description | Sets the element that the popup is positioned against. Without it, the popup uses the active trigger. |
| Prop | positionMethod |
|---|---|
| Type | "absolute" | "fixed" |
| Default | "absolute" |
| Description | Sets the CSS position that places the popup. |
| Prop | collisionBoundary |
|---|---|
| Type | "clipping-ancestors" | Element | Element[] | Rect |
| Default | "clipping-ancestors" |
| Description | Sets the area that the popup must stay in: the ancestors that clip it, one or several elements, or a rectangle. |
| Prop | collisionPadding |
|---|---|
| Type | number | { top?: number; right?: number; bottom?: number; left?: number } |
| Default | 5 |
| Description | Sets the distance in pixels that the popup keeps from the edge of the collision boundary. |
| Prop | collisionAvoidance |
|---|---|
| Type | CollisionAvoidance |
| Default | { fallbackAxisSide: "none" } |
| Description | Sets how the popup reacts when it doesn't fit in the collision boundary. side takes "flip" to move the popup to the opposite side, or "shift" to keep the side and push the popup back into the boundary. align takes "flip" to swap start and end, or "shift" to push the popup along its side. fallbackAxisSide takes "start" or "end" to let the popup move to a side on the other axis. Each of them takes "none" to switch its reaction off. A navigation menu inside another one uses "end" for fallbackAxisSide by default. |
| Prop | sticky |
|---|---|
| Type | boolean |
| Default | false |
| Description | Keeps the popup in the viewport after its trigger has been scrolled out of view. |
| Prop | arrowPadding |
|---|---|
| Type | number |
| Default | 5 |
| Description | Sets the minimum distance between an arrow and the edges of the popup. The positioner renders no arrow, so it has no effect. |
| Prop | disableAnchorTracking |
|---|---|
| Type | boolean |
| Default | false |
| Description | Stops the popup from following its trigger when the layout shifts. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the positioner with another component. |