Skip to main content

navigation menu

A collection of links for navigating websites.

Philosophy

Navigation menus serve a different purpose than dropdown menus — they're for wayfinding, not actions. The distinction matters for accessibility: navigation menus use <nav> and link semantics, while dropdown menus use role="menu" and button semantics. We expose viewport and indicator sub-components for advanced hover/focus animations.

Installation


npx @gentleduck/cli add navigation-menu

npx @gentleduck/cli add navigation-menu

Usage

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@/components/ui/navigation-menu"
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@/components/ui/navigation-menu"
<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuTrigger>Item One</NavigationMenuTrigger>
      <NavigationMenuContent>
        <NavigationMenuLink>Link</NavigationMenuLink>
      </NavigationMenuContent>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>
<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuTrigger>Item One</NavigationMenuTrigger>
      <NavigationMenuContent>
        <NavigationMenuLink>Link</NavigationMenuLink>
      </NavigationMenuContent>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>

Component Composition

Loading diagram...

You can use the asChild prop to make another component look like a navigation menu trigger. Here's an example of a link that looks like a navigation menu trigger.

components/example-navigation-menu.tsx
import { Link } from "next/link"
 
export function NavigationMenuDemo() {
  return (
    <NavigationMenuItem>
      <NavigationMenuLink asChild>
        <Link href="/docs">Documentation</Link>
      </NavigationMenuLink>
    </NavigationMenuItem>
  )
}
components/example-navigation-menu.tsx
import { Link } from "next/link"
 
export function NavigationMenuDemo() {
  return (
    <NavigationMenuItem>
      <NavigationMenuLink asChild>
        <Link href="/docs">Documentation</Link>
      </NavigationMenuLink>
    </NavigationMenuItem>
  )
}

API Reference

Root container that wraps the navigation menu and optionally renders the viewport.

PropTypeDefaultDescription
valuestring--Controlled value of the active menu item
defaultValuestring--Default active value for uncontrolled usage
onValueChange(value: string) => void--Callback when the active value changes
viewportbooleantrueWhether to render the NavigationMenuViewport automatically
dir'ltr' | 'rtl'--Text direction. Resolved by primitives useDirection (dir prop -> DirectionProvider -> 'ltr') and inherited by descendants.
orientation'horizontal' | 'vertical''horizontal'The orientation of the menu
delayDurationnumber200Duration in ms from when the pointer enters a trigger until the content opens
skipDelayDurationnumber300Duration in ms a user has to enter another trigger without incurring a delay again
classNamestring--Additional CSS classes for the root element
childrenReact.ReactNode--Navigation menu list and other elements
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>--Additional props inherited from NavigationMenu.Root.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the list element
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>--Additional props inherited from NavigationMenu.List.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the menu item
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item>--Additional props inherited from NavigationMenu.Item.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the trigger
childrenReact.ReactNode--Trigger label content. A chevron icon is appended automatically
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>--Additional props inherited from NavigationMenu.Trigger.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the content panel
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>--Additional props inherited from NavigationMenu.Content.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the link
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link>--Additional props inherited from NavigationMenu.Link.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the viewport
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>--Additional props inherited from NavigationMenu.Viewport.
PropTypeDefaultDescription
classNamestring--Additional CSS classes for the indicator
...propsReact.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>--Additional props inherited from NavigationMenu.Indicator.

A cva variant function that returns the default trigger styling classes. Use it to style non-trigger elements (e.g. plain links) to match the trigger appearance.

import { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu"
 
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
  Documentation
</NavigationMenuLink>
import { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu"
 
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
  Documentation
</NavigationMenuLink>

RTL Support

Set dir="rtl" on NavigationMenu for a local override, or set DirectionProvider once at app/root level for global direction.