NavigationMenu
NavigationMenu is a navigation component for moving between sections of a site or app — supports both horizontal bars and sidebars, with submenus and collapse mode.
Playground
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink href="#" active icon={<Home className="icon-sm" />}>Home</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem value="products">
<NavigationMenuTrigger icon={<Package className="icon-sm" />}>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink href="#">All Products</NavigationMenuLink>
<NavigationMenuLink href="#">Featured</NavigationMenuLink>
<NavigationMenuLink href="#">New Arrivals</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem value="resources">
<NavigationMenuTrigger icon={<BookOpen className="icon-sm" />}>Resources</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink href="#">Documentation</NavigationMenuLink>
<NavigationMenuLink href="#">Blog</NavigationMenuLink>
<NavigationMenuLink href="#">Support</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" icon={<Tag className="icon-sm" />}>Pricing</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" icon={<Users className="icon-sm" />}>About</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" icon={<Mail className="icon-sm" />}>Contact</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>Variants
Sizes
smmddefaultlg| Size | Height | Padding | Gap | Icon | Font | Preview |
|---|---|---|---|---|---|---|
sm | 32px | 12px | 8px | 14px | 13px | |
md | 36px | 14px | 8px | 16px | 14px | |
default | 40px | 16px | 8px | 16px | 14px | |
lg | 48px | 24px | 8px | 16px | 16px |
Features
Sub Menus
In horizontal mode, dropdowns open on hover. In vertical mode, items expand accordion-style on click.
<NavigationMenuItem value="products">
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink href="#">All Products</NavigationMenuLink>
<NavigationMenuLink href="#">Featured</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>Collapsed Mode
The collapsed prop shows icons only. Use collapsedWidth to customize the width (default: 64px).
<NavigationMenu orientation="vertical" collapsed>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink href="#"
icon={<Home className="icon-sm" />}>
Home
</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>Active State
The active prop visually highlights the current page and automatically sets aria-current="page".
<NavigationMenuLink href="#" active
icon={<Home className="icon-sm" />}>
Home
</NavigationMenuLink>Group Label
Use NavigationMenuGroup to divide items into sections and the label prop to display a group header.
<NavigationMenu orientation="vertical">
<NavigationMenuList>
<NavigationMenuGroup label="Main">
<NavigationMenuItem>
<NavigationMenuLink href="#">Home</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuGroup>
<NavigationMenuGroup label="Settings">
<NavigationMenuItem>
<NavigationMenuLink href="#">General</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuGroup>
</NavigationMenuList>
</NavigationMenu>Custom Link (asChild)
Use the asChild prop to compose with custom link components such as Next.js Link.
import Link from 'next/link'
<NavigationMenuLink asChild active>
<Link href="/dashboard">Dashboard</Link>
</NavigationMenuLink>API
Component Structure
NavigationMenu— Radix NavigationMenu + Collapsible.ListList container.ItemPropsMenu item (value · defaultOpen).TriggerPropsSubmenu trigger (icon · chevronIcon).ContentSubmenu content.LinkPropsLink (active · asChild · icon).GroupPropsGroup (with label).IndicatorActive indicator.ViewportViewport (horizontal only)Props
NavigationMenu
orientation"horizontal""horizontal" | "vertical"Layout direction
size"default""sm" | "md" | "default" | "lg"Menu item size
collapsedfalsebooleanVertical only: show icons only (collapsed sidebar)
width256number | stringVertical only: sidebar width (px number or CSS string)
collapsedWidthsm:56 / md:60 / default:64 / lg:72number | stringVertical only: width when collapsed (auto-calculated by size, overridable with px or CSS string)
radius"lg""sm" | "md" | "lg" | "xl"Border radius (horizontal: container/item concentric, vertical: applied directly)
fontWeight"normal""normal" | "semibold"Menu item font weight (active state is always semibold)
delayDuration200numberHorizontal only: delay before opening on hover (ms)
skipDelayDuration300numberHorizontal only: skip delay when moving between triggers (ms)
valueundefinedstringActive menu item value (controlled mode)
defaultValueundefinedstringDefault active value (uncontrolled mode)
onValueChangeundefined(value: string) => voidCallback when active item changes
| Name | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction |
size | "sm" | "md" | "default" | "lg" | "default" | Menu item size |
collapsed | boolean | false | Vertical only: show icons only (collapsed sidebar) |
width | number | string | 256 | Vertical only: sidebar width (px number or CSS string) |
collapsedWidth | number | string | sm:56 / md:60 / default:64 / lg:72 | Vertical only: width when collapsed (auto-calculated by size, overridable with px or CSS string) |
radius | "sm" | "md" | "lg" | "xl" | "lg" | Border radius (horizontal: container/item concentric, vertical: applied directly) |
fontWeight | "normal" | "semibold" | "normal" | Menu item font weight (active state is always semibold) |
delayDuration | number | 200 | Horizontal only: delay before opening on hover (ms) |
skipDelayDuration | number | 300 | Horizontal only: skip delay when moving between triggers (ms) |
value | string | undefined | Active menu item value (controlled mode) |
defaultValue | string | undefined | Default active value (uncontrolled mode) |
onValueChange | (value: string) => void | undefined | Callback when active item changes |
NavigationMenuItem
valueundefinedstringRadix identifier (for horizontal mode)
defaultOpenfalsebooleanVertical only: initial open state of submenu
| Name | Type | Default | Description |
|---|---|---|---|
value | string | undefined | Radix identifier (for horizontal mode) |
defaultOpen | boolean | false | Vertical only: initial open state of submenu |
NavigationMenuTrigger
iconundefinedReactNodeIcon displayed before the label
chevronIcon内蔵SVGReactNodeCustomize the chevron icon (horizontal: ▼, vertical: ▶)
| Name | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | undefined | Icon displayed before the label |
chevronIcon | ReactNode | 内蔵SVG | Customize the chevron icon (horizontal: ▼, vertical: ▶) |
NavigationMenuLink
activefalsebooleanRepresents the current page (aria-current="page")
asChildfalsebooleanCompose with custom link components (Radix Slot)
iconundefinedReactNodeIcon displayed before the label
hrefundefinedstringLink URL
| Name | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Represents the current page (aria-current="page") |
asChild | boolean | false | Compose with custom link components (Radix Slot) |
icon | ReactNode | undefined | Icon displayed before the label |
href | string | undefined | Link URL |
NavigationMenuGroup
labelundefinedstringGroup header label
| Name | Type | Default | Description |
|---|---|---|---|
label | string | undefined | Group header label |
Customization
NavigationMenuContent Place any JSX inside to create mega menus, card layouts, and more.
Mega Menu
<NavigationMenuContent>
<div className="grid grid-cols-3 gap-4 p-4 w-[480px]">
<div>
<h4 className="text-xs font-semibold uppercase mb-2">
Electronics
</h4>
<NavigationMenuLink href="#">
Smartphones
</NavigationMenuLink>
<NavigationMenuLink href="#">
Laptops
</NavigationMenuLink>
</div>
{/* ...more columns */}
</div>
</NavigationMenuContent>Card Layout
<NavigationMenuContent>
<div className="grid grid-cols-2 gap-2 p-3 w-[400px]">
<a href="#" className="block p-3 rounded-lg
hover:bg-background-muted">
<div className="text-sm font-semibold">
Documentation
</div>
<div className="text-xs text-text-muted">
Getting started guides and API references.
</div>
</a>
{/* ...more cards */}
</div>
</NavigationMenuContent>Tip:NavigationMenuContent content layout is completely free — grids, flex, cards, customize to fit your project.chevronIcon prop lets you swap the chevron icon as well.
Anatomy
h-10 (40px)px-4 (16px)gap-2 (8px)Best Practices
Do
- ✓Use for the site's primary navigation sections
- ✓Use active to clearly indicate the current page
- ✓Pair icons with labels in sidebars
- ✓Group related links using Group
Don't
- ✗Avoid nesting more than 3 levels deep
- ✗Don't crowd too many items into horizontal mode
- ✗Don't use icon-only in collapsed mode without tooltips
- ✗Don't use for triggering actions — use Dropdown instead
Accessibility
Keyboard
ARIA / WCAG
aria-label="navigation"set on the nav elementaria-current="page"automatically set on active links- Full keyboard support via Radix NavigationMenu + Collapsible
- Follows WAI-ARIA Disclosure Navigation Pattern