NavigationMenu
A site's top navigation: links and buttons that reveal panels of links, from a short list to a full-width mega menu.
import { NavigationMenu } from "@meridui/react";
export function SiteNav() {
return (
<NavigationMenu.Root aria-label="Product site">
<NavigationMenu.List>
<NavigationMenu.Item value="products">
<NavigationMenu.Trigger>Products</NavigationMenu.Trigger>
<NavigationMenu.Content fullWidth>
<NavigationMenu.Link href="/analytics" description="Dashboards, funnels and retention.">
Analytics
</NavigationMenu.Link>
<NavigationMenu.Link href="/billing" description="Invoices, plans and usage-based pricing.">
Billing
</NavigationMenu.Link>
{/* … */}
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item value="resources">
<NavigationMenu.Trigger>Resources</NavigationMenu.Trigger>
<NavigationMenu.Content>
<NavigationMenu.Link href="/docs">Documentation</NavigationMenu.Link>
<NavigationMenu.Link href="/guides">Guides</NavigationMenu.Link>
<NavigationMenu.Link href="/changelog">Changelog</NavigationMenu.Link>
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Link href="/pricing" active>Pricing</NavigationMenu.Link>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>
);
}Import
import { NavigationMenu } from "@meridui/react";Anatomy
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item value="products">
<NavigationMenu.Trigger />
<NavigationMenu.Content>
<NavigationMenu.Link />
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Link />
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>- Root is the
<nav>landmark and holds which panel is open (one at a time). - List and Item are the
<ul>and<li>of the bar. - Trigger is a disclosure
<button>; Content is its panel of links.fullWidthspans the bar for a mega menu. - Link is an
<a>, directly in an Item (a top-level link) or inside Content.descriptionadds a second line.
Examples
Router links
asChild renders your router's link with the same styling and behaviour; active sets aria-current="page".
import NextLink from "next/link";
<NavigationMenu.Link asChild active={pathname === "/pricing"}>
<NextLink href="/pricing">Pricing</NextLink>
</NavigationMenu.Link>Mega menu
Pass fullWidth to Content: the panel spans the whole bar and lays links out in a responsive grid. Below 640px every panel spans the bar.
API reference
Root
Accepts every <nav> attribute.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | – | Controlled open item ("" when none). |
defaultValue | string | "" | Initially open item when uncontrolled. |
onValueChange | (value: string) => void | – | Called with the open item value. |
openDelay | number | 150 | Hover delay before a panel opens, in ms. Clicks and keys open at once. |
closeDelay | number | 250 | Delay before a panel closes after the pointer leaves, in ms. |
aria-label | string | "Main" | Accessible name of the navigation landmark. |
ref | Ref<HTMLElement> | – | Forwarded ref to the <nav>. |
Item
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | – | Unique value; needed for controlled use. Defaults to a generated id. |
Trigger, Content
Trigger accepts every <button> attribute; Content every <div> attribute.
| Prop | Type | Default | Description |
|---|---|---|---|
Content fullWidth | boolean | false | Span the full width of the bar (a mega menu). |
Link
Accepts every <a> attribute.
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Marks the current page (aria-current="page"). |
description | string | – | Second line under the label, for links inside a panel. |
asChild | boolean | false | Render the single child element (a router link) instead of an <a>. |
ref | Ref<HTMLAnchorElement> | – | Forwarded ref. |
Styling
| Class | Element |
|---|---|
.mrd-navmenu | Root |
.mrd-navmenu__list, .mrd-navmenu__item | List and Item |
.mrd-navmenu__trigger, .mrd-navmenu__chevron | Trigger and its icon |
.mrd-navmenu__content | Content |
.mrd-navmenu__link, .mrd-navmenu__link-title, .mrd-navmenu__link-description | Link parts |
| Attribute | On | Values |
|---|---|---|
data-state | Root, Item, Trigger, Content | open, closed |
data-full | Content | present with fullWidth |
data-active | Link | present when active |
Accessibility
Follows the WAI-ARIA Disclosure navigation menu example rather than role="menubar": site navigation is a list of links, and every trigger and link stays in the Tab order. Panels stay in the DOM while closed (hidden), so their links are crawlable. Focus leaving the nav, Escape or an outside press close the open panel.
| Key | Action |
|---|---|
| EnterSpace | On a trigger: open or close its panel. |
| ArrowDown | On a trigger: open and focus the first link. In a panel: next link. |
| ArrowUp | In a panel: previous link. |
| ArrowRightArrowLeft | Next / previous trigger or top-level link (mirrored in RTL). |
| HomeEnd | First / last trigger or top-level link. |
| Escape | Close the panel and return focus to its trigger. |
| Tab | Move through triggers and links in order. |
Guidelines
Do
Keep top-level labels short and put the most-visited destinations first.
Avoid
Use NavigationMenu for app commands. Actions belong in a DropdownMenu or Toolbar.
Related
- SidebarNav: vertical navigation for app sidebars.
- Breadcrumb: where the current page sits.