Navigation Menu
A navigation bar of links and menus that open panels of content.
Usage
NavigationMenu is a compound component built on Base UI's Navigation Menu. The root coordinates the bar and shares variant, size, orientation, and the trigger icon with every item. The single popup morphs — moving and resizing — between items as you hover across the bar:
NavigationMenuList— the row (or column) of items.NavigationMenuItem— wraps one entry: a trigger + content, or a single link.NavigationMenuTrigger— the label that opens an item's panel on hover or focus.NavigationMenuIcon— the trigger's open/close indicator; flips while open. Override its kind per-trigger or drop it withicon={false}on the root.NavigationMenuContent— the panel for a trigger. Lay your links out inside it however you like — a list, a grid, a featured card.NavigationMenuLink— a link, both inside a panel and as a standalone top-level item (give itclassName="w-auto"so it sizes to its label in the bar).NavigationMenuViewport— the surface a panel renders into. The root renders one automatically; render your own only for inline submenus.NavigationMenuPositioner— the portalled, auto-positioned wrapper around the popup. Rendered automatically; passviewport={false}on the root to opt out.
Reach for a NavigationMenu for marketing-style site navigation with multi-column panels and descriptions. For a single menu of actions opened from a button, use a Dropdown Menu; for an application command bar (File / Edit / View), use a Menubar; for a flat row of section links, use Navigation.
Examples
Default
A bar with two panel-opening items and one plain link. Each panel is just markup inside NavigationMenuContent — here a grid of NavigationMenuLink cards with an icon, a title, and a description. The popup morphs to fit whichever panel is open.
Variants
variant styles the triggers: pill (default) gives each a hover/active background, while line draws an animated underline.
Sizes
size on the root scales the triggers, popup radius, and link padding together — sm, md (default), or lg.
Indicator
icon on the root sets the open/close indicator next to every trigger: a chevron (default), a caret, or a plus that morphs into a minus. Set icon={false} to drop it, or override a single trigger by passing icon to its NavigationMenuIcon.
Vertical
Set orientation="vertical" to stack the bar into a sidebar; each panel opens to the inline-end side. Give triggers w-full justify-start and push the indicator to the edge with ms-auto.
Backdrop
Set backdrop to dim and blur the page behind the open panel — useful for a prominent mega-menu that should pull focus away from the page.
Nested submenus
Open a deeper level in its own panel by nesting a second NavigationMenu (set orientation="vertical") inside a NavigationMenuContent. The nested menu renders its own portalled popup, opening to the side of the parent panel — just like a submenu.
Nested inline submenus
To switch panels within the same popup — a sidebar of categories beside a detail pane — nest a NavigationMenu with viewport={false} and render your own NavigationMenuViewport next to its list. Use defaultValue to open one category on mount, and give each NavigationMenuItem a value so the list can drive the shared viewport.
RTL
Every Appica UI component supports right-to-left layouts out of the box. Set the dir attribute on a container (commonly your <html> element) so CSS logical properties resolve correctly, and wrap your tree in DirectionProvider so direction-aware behavior — roving focus along the bar, popup placement, and the morph direction — follows the same direction.
The bar lays out from the right, arrow-key focus reverses, the panel anchors from the trigger's leading edge, and a vertical menu's panels open toward the inline-start side. For setup details and caveats, see the RTL guide.
Scoped RTL needs the direction on the positioner
The popup portals to <body>, so its start/end alignment mirrors from the document direction (read from CSS,
not from DirectionProvider) — automatic when <html dir="rtl">. If you instead scope RTL to a subtree of an LTR page,
set dir="rtl" on the NavigationMenu root so the morphing panel still mirrors. See
Floating popups in a scoped RTL region.
API reference
NavigationMenu wraps Base UI's Navigation Menu. Each part forwards every remaining prop to the matching Base UI primitive, so anything it accepts works here — the tables below list the Appica additions and the most common props. See the Base UI docs for the complete API.
NavigationMenu
The root. Coordinates the bar, owns the open state, and shares styling with every item.
NavigationMenuList
The row (or column) of items.
NavigationMenuItem
Wraps one entry — a trigger with content, or a single link.
NavigationMenuTrigger
The label that opens an item's panel. Inherits the root's variant, size, and orientation.
NavigationMenuIcon
The trigger's open/close indicator. Reads the root's icon kind; flips or morphs while the panel is open.
NavigationMenuContent
The panel for a trigger. Renders into the active viewport; lay your links out inside it freely.
NavigationMenuLink
A link — inside a panel or as a standalone bar item. Renders an <a>; use render to project it onto a router link. Forwards every native anchor prop (href, target, rel, …).
NavigationMenuPositioner
The portalled, auto-positioned wrapper around the popup. Rendered automatically unless viewport={false}; render it yourself only for a fully custom popup.
NavigationMenuViewport
The surface a panel renders into. The root renders one inside its popup automatically; render your own (with viewport={false}) only for an inline submenu.
Accessibility
- The bar renders a navigation landmark — give the root an
aria-label. Triggers carryaria-expandedand own their panel viaaria-controls. - ↑/↓/←/→ move focus along the bar and into the open panel; Enter / Space open an item; Escape closes the panel back to its trigger; Tab moves through the panel's links.
- Panels open on hover and on keyboard focus, so the menu is reachable without a pointer.
disabledtriggers are skipped by keyboard navigation.- The morph, panel, and backdrop transitions are all skipped when the user prefers reduced motion.