Navigation Menu
A horizontal navigation bar with multi-column dropdown menus. Supports grouped links with optional descriptions, plain links, and keyboard navigation.
Preview
Anatomy
| Part | Element | Description |
|---|---|---|
| Root | <nav> | Landmark with aria-label='Main navigation'. |
| Trigger | <button> | aria-haspopup=menu + aria-expanded. Opens on hover/focus. |
| Link | <a> | Simple navigation item with no dropdown. |
| Dropdown | div[role=menu] | Positioned below trigger. Closes on Escape or click outside. |
| Group | div | Optional titled column within the dropdown. |
| Link item | a[role=menuitem] | Label + optional description. Closes dropdown on click. |
Keyboard interactions
| Key | Action |
|---|---|
| Tab / Shift+Tab | Move focus between triggers and plain links |
| Enter / Space | Open dropdown or follow link |
| Arrow Down | Open dropdown, focus first item |
| Escape | Close open dropdown, return focus to trigger |
| Home / End | Focus first / last item in open dropdown |
Implementation
NavigationMenu.tsx
tsx
import { NavigationMenu } from "@/components/ui/NavigationMenu";
const items = [
{
label: "Products",
groups: [
{
title: "Design",
links: [
{ label: "Design System", href: "/design-system", description: "Tokens, components, guidelines" },
{ label: "Figma Library", href: "/figma" },
],
},
{
title: "Develop",
links: [
{ label: "React Components", href: "/react" },
{ label: "CLI", href: "/cli" },
],
},
],
},
{ label: "Docs", href: "/docs" },
{ label: "Blog", href: "/blog" },
];
<NavigationMenu items={items} />Guidelines
- →Keep top-level items to five or fewer — cognitive load increases steeply beyond that.
- →Use groups and titles when a dropdown contains more than four links; grouping reveals hierarchy.
- →Add descriptions only to the most important links — description parity across all items creates visual noise.
- →Dropdowns open on hover on desktop but must also open on focus for keyboard users.
- →Do not nest dropdowns more than one level — use a separate dedicated page for deep hierarchies.