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"
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Item One</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Link</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
Component Composition
Link
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.
import Link from "next/link"
export function NavigationMenuDemo() {
return (
<NavigationMenuItem>
<NavigationMenuLink asChild>
<Link href="/www">Documentation</Link>
</NavigationMenuLink>
</NavigationMenuItem>
)
}
RTL Support
Set the direction once with DirectionProvider (or <html dir="rtl">) and the navigation menu follows. Content aligns to the right, slides in from the side of the trigger you moved to, and arrow keys move through the list in visual order.
Motion
Use MotionNavigationMenu for a scaleIn entrance animation (fade, scale, and blur) with a bouncy spring transition, powered by motion.
motion package. Use MotionNavigationMenu instead of NavigationMenu. All other sub-components stay the same.API Reference
NavigationMenu
Root container that wraps the navigation menu and optionally renders the viewport.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Controlled value of the active menu item |
defaultValue | string | - | Default active value for uncontrolled usage |
onValueChange | (value: string) => void | - | Callback when the active value changes |
viewport | boolean | true | Whether to render the NavigationMenuViewport automatically |
dir | 'ltr' | 'rtl' | - | Text direction. Resolved by primitives useDirection (dir prop -> DirectionProvider -> <html dir>) and inherited by descendants. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | The orientation of the menu |
delayDuration | number | 200 | Duration in ms from when the pointer enters a trigger until the content opens |
skipDelayDuration | number | 300 | Duration in ms a user has to enter another trigger without incurring a delay again |
className | string | - | Additional CSS classes for the root element |
children | React.ReactNode | - | Navigation menu list and other elements |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> | - | Additional props inherited from NavigationMenu.Root. |
NavigationMenuList
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the list element |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> | - | Additional props inherited from NavigationMenu.List. |
NavigationMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the menu item |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item> | - | Additional props inherited from NavigationMenu.Item. |
NavigationMenuTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the trigger |
children | React.ReactNode | -- | Trigger label content. A chevron icon is appended automatically |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> | - | Additional props inherited from NavigationMenu.Trigger. |
NavigationMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the content panel |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> | - | Additional props inherited from NavigationMenu.Content. |
NavigationMenuLink
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the link |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link> | - | Additional props inherited from NavigationMenu.Link. |
NavigationMenuViewport
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the viewport |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> | - | Additional props inherited from NavigationMenu.Viewport. |
NavigationMenuIndicator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the indicator |
...props | React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> | - | Additional props inherited from NavigationMenu.Indicator. |
navigationMenuTriggerStyle
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>
MotionNavigationMenu
Same props as NavigationMenu. Adds a scaleIn entrance animation (fade, scale, and blur) with a bouncy spring transition via motion. Requires the motion package.