Navigation Menu
Menus that open on hover and share one floating panel, so moving between triggers resizes and slides the same surface instead of opening a new popover.
Installation#
Usage#
import {
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuLink,
} from "@/components/ui/navigation-menu"
export function Example() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Product</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink href="/analytics">Analytics</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}Columns#
For a wide menu, set NavigationMenuGroups side by side, each under a NavigationMenuGroupLabel, and close the panel with a NavigationMenuFooter for the link to everything else.
Featured card#
variant="card" turns a link into a featured block: a NavigationMenuLinkMedia picture over its title and description, beside the rows. The whole card is the link.
Category rail#
A NavigationMenuSub nests a menu inside the panel: a rail of categories down the side and a pane that switches the moment the pointer reaches the next one, with no delay. Its defaultValue picks the pane that shows first.
Icon tiles#
NavigationMenuLinkIcon sets a row's glyph in a 32px tile. A brand logo keeps its own colours there, where a bare icon in a row is muted, so it's the pick for integrations and apps.
Timing#
A trigger opens after delayDuration (200ms), so a cursor passing over the bar doesn't flash every menu. Reach a sibling trigger within skipDelayDuration (300ms) and it opens at once.
Without the shared panel#
viewport={false} gives each trigger its own panel, opened under it. Switching closes one and opens the next, so reach for it only when the menus are far apart.
Density#
density on the root sets the row height of every link in the menu. The panel padding stays put, so the corners stay concentric in both.
API reference#
NavigationMenu
The root. Forwards Radix's delayDuration, skipDelayDuration and value / onValueChange. viewport (default true) renders the shared panel; density sets the row height of every link.
NavigationMenuList / NavigationMenuItem
The row and each entry in it. An item holds a trigger and its content, or a single NavigationMenuLink variant="bar".
NavigationMenuTrigger / NavigationMenuContent
The chip in the bar and the contents of its panel. The caret turns while the panel is open.
NavigationMenuLink
variant: "row" (default), a row in a panel; "bar", a plain entry beside the triggers; or "card", a featured block. active marks the current page. Wrap a title and a NavigationMenuLinkDescription in NavigationMenuLinkText for a described row.
NavigationMenuLinkIcon / NavigationMenuLinkMedia
A 32px tile for a row's glyph, where a brand logo keeps its colours, and the inset picture frame of a card link. Put an <img> inside the frame; it owns an aspect-video ratio you can override.
NavigationMenuGroup / NavigationMenuGroupLabel / NavigationMenuFooter
A labelled column of links, its small muted heading, and the panel's foot under a hairline. Each is optional: a group reads fine without its label, and a footer with nothing above it drops its rule.
NavigationMenuSub / NavigationMenuSubViewport
A menu inside a panel. The Sub holds a NavigationMenuList rail (vertical by default) and, after it, the viewport the active pane shows in. It forwards Radix's defaultValue, value and orientation.
NavigationMenuIndicator / NavigationMenuViewport
The tip that slides under the active trigger (optional, the list's last child), and the shared panel, which the root already renders.