Navigation Menu
Navigation Menu provides Runtime-backed navigation disclosure, focus management, and floating content positioning.
---import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle,} from "@/components/starwind/navigation-menu";import AlertCircle from "@tabler/icons/outline/alert-circle.svg";import CircleCheck from "@tabler/icons/outline/circle-check.svg";import CircleDashed from "@tabler/icons/outline/circle-dashed.svg";
const components = [ { title: "Alert Dialog", href: "/docs/components/alert-dialog/", description: "A modal dialog that interrupts the user with important content and expects a response.", }, { title: "Hover Card", href: "/docs/components/hover-card/", description: "For sighted users to preview content available behind a link.", }, { title: "Progress", href: "/docs/components/progress/", description: "Displays an indicator showing the completion progress of a task.", }, { title: "Scroll Area", href: "/docs/components/scroll-area/", description: "Augments native scroll functionality for custom, cross-browser styling.", }, { title: "Tabs", href: "/docs/components/tabs/", description: "A set of layered sections of content displayed one at a time.", }, { title: "Tooltip", href: "/docs/components/tooltip/", description: "A popup that provides information when an element is focused or hovered.", },];---
<NavigationMenu size="md" aria-label="Documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul class="w-108"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">Introduction</div> <div class="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="/docs/getting-started/installation/"> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">Installation</div> <div class="text-muted-foreground line-clamp-2"> How to install dependencies and structure your app. </div> </div> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="/docs/getting-started/theming/"> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">Theming</div> <div class="text-muted-foreground line-clamp-2"> Customize colors, typography, and design tokens. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="components" class="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[500px] gap-2 md:w-[600px] md:grid-cols-2 lg:w-[700px]"> {components.map((component) => ( <li> <NavigationMenuLink href={component.href}> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">{component.title}</div> <div class="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[240px]"> <li> <NavigationMenuLink href="#backlog" class="flex-row items-center gap-2"> <AlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#to-do" class="flex-row items-center gap-2"> <CircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#done" class="flex-row items-center gap-2"> <CircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" class={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList></NavigationMenu>import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle,} from "@/components/starwind/navigation-menu";import { IconAlertCircle as AlertCircle, IconCircleCheck as CircleCheck, IconCircleDashed as CircleDashed,} from "@tabler/icons-react";
const components = [ { title: "Alert Dialog", href: "/docs/components/alert-dialog/", description: "A modal dialog that interrupts the user with important content and expects a response.", }, { title: "Hover Card", href: "/docs/components/hover-card/", description: "For sighted users to preview content available behind a link.", }, { title: "Progress", href: "/docs/components/progress/", description: "Displays an indicator showing the completion progress of a task.", }, { title: "Scroll Area", href: "/docs/components/scroll-area/", description: "Augments native scroll functionality for custom, cross-browser styling.", }, { title: "Tabs", href: "/docs/components/tabs/", description: "A set of layered sections of content displayed one at a time.", }, { title: "Tooltip", href: "/docs/components/tooltip/", description: "A popup that provides information when an element is focused or hovered.", },];
export function Example() { return ( <> <NavigationMenu size="md" aria-label="Documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul className="w-108"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">Introduction</div> <div className="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="/docs/getting-started/installation/"> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">Installation</div> <div className="text-muted-foreground line-clamp-2"> How to install dependencies and structure your app. </div> </div> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="/docs/getting-started/theming/"> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">Theming</div> <div className="text-muted-foreground line-clamp-2"> Customize colors, typography, and design tokens. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="components" className="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[500px] gap-2 md:w-[600px] md:grid-cols-2 lg:w-[700px]"> {components.map((component) => ( <li key={`${component.href}-${component.title}`}> <NavigationMenuLink href={component.href}> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">{component.title}</div> <div className="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[240px]"> <li> <NavigationMenuLink href="#backlog" className="flex-row items-center gap-2"> <AlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#to-do" className="flex-row items-center gap-2"> <CircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#done" className="flex-row items-center gap-2"> <CircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" className={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </> );}Installation
pnpx starwind@latest add navigation-menunpx starwind@latest add navigation-menuyarn dlx starwind@latest add navigation-menuUsage
---import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger,} from "@/components/starwind/navigation-menu";---import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger,} from "@/components/starwind/navigation-menu";<NavigationMenu> <NavigationMenuList> <NavigationMenuItem value="item-one"> <NavigationMenuTrigger>Item One</NavigationMenuTrigger> <NavigationMenuContent> <NavigationMenuLink href="/docs/">Link</NavigationMenuLink> </NavigationMenuContent> </NavigationMenuItem> </NavigationMenuList></NavigationMenu>import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger } from "@/components/starwind/navigation-menu";
export function Example() { return ( <> <NavigationMenu> <NavigationMenuList> <NavigationMenuItem value="item-one"> <NavigationMenuTrigger>Item One</NavigationMenuTrigger> <NavigationMenuContent> <NavigationMenuLink href="/docs/">Link</NavigationMenuLink> </NavigationMenuContent> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </> );}Composition
Use the following composition to build a NavigationMenu:
NavigationMenu└── NavigationMenuList ├── NavigationMenuItem │ ├── NavigationMenuTrigger │ └── NavigationMenuContent │ ├── NavigationMenuLink │ └── NavigationMenuLink └── NavigationMenuItem └── NavigationMenuLinkSizes
NavigationMenu defaults to size="md". Set size once to keep native triggers, List spacing, trigger-style Links, and portaled content aligned. Use contentSize only when the shared popup should intentionally use a different size.
---import AlertCircle from "@tabler/icons/outline/alert-circle.svg";import CircleCheck from "@tabler/icons/outline/circle-check.svg";import CircleDashed from "@tabler/icons/outline/circle-dashed.svg";import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle,} from "@/components/starwind/navigation-menu";
const componentLinks = [ { title: "Alert Dialog", href: "/docs/components/alert-dialog/", description: "A modal dialog that asks for a response.", }, { title: "Hover Card", href: "/docs/components/hover-card/", description: "Preview content available behind a link.", },];---
<div class="grid gap-6"> <div class="space-y-3"> <div class="text-muted-foreground text-sm font-medium">Small (sm)</div> <NavigationMenu size="sm" aria-label="Small documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="small-getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul class="w-96"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div class="flex flex-col gap-1 text-sm"> <div class="leading-none font-medium">Introduction</div> <div class="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="small-components" class="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[400px] gap-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> {componentLinks.map((component) => ( <li> <NavigationMenuLink href={component.href}> <div class="flex flex-col gap-1 text-sm"> <div class="leading-none font-medium">{component.title}</div> <div class="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="small-status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[200px]"> <li> <NavigationMenuLink href="#small-backlog" class="flex-row items-center gap-2"> <AlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#small-to-do" class="flex-row items-center gap-2"> <CircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#small-done" class="flex-row items-center gap-2"> <CircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" class={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div>
<div class="space-y-3"> <div class="text-muted-foreground text-sm font-medium">Medium (md)</div> <NavigationMenu size="md" aria-label="Medium documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="medium-getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul class="w-108"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">Introduction</div> <div class="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="medium-components" class="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[500px] gap-2 md:w-[600px] md:grid-cols-2 lg:w-[700px]"> {componentLinks.map((component) => ( <li> <NavigationMenuLink href={component.href}> <div class="flex flex-col gap-1.5"> <div class="leading-none font-medium">{component.title}</div> <div class="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="medium-status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul class="grid w-[240px]"> <li> <NavigationMenuLink href="#medium-backlog" class="flex-row items-center gap-2"> <AlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#medium-to-do" class="flex-row items-center gap-2"> <CircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#medium-done" class="flex-row items-center gap-2"> <CircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" class={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div></div>import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle,} from "@/components/starwind/navigation-menu";import { IconAlertCircle, IconCircleCheck, IconCircleDashed } from "@tabler/icons-react";
const componentLinks = [ { title: "Alert Dialog", href: "/docs/components/alert-dialog/", description: "A modal dialog that asks for a response.", }, { title: "Hover Card", href: "/docs/components/hover-card/", description: "Preview content available behind a link.", },];
export function Example() { return ( <div className="grid gap-6"> <div className="space-y-3"> <div className="text-muted-foreground text-sm font-medium">Small (sm)</div> <NavigationMenu size="sm" aria-label="Small documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="small-getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul className="w-96"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div className="flex flex-col gap-1 text-sm"> <div className="leading-none font-medium">Introduction</div> <div className="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="small-components" className="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[400px] gap-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> {componentLinks.map((component) => ( <li key={component.href}> <NavigationMenuLink href={component.href}> <div className="flex flex-col gap-1 text-sm"> <div className="leading-none font-medium">{component.title}</div> <div className="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="small-status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[200px]"> <li> <NavigationMenuLink href="#small-backlog" className="flex-row items-center gap-2"> <IconAlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#small-to-do" className="flex-row items-center gap-2"> <IconCircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#small-done" className="flex-row items-center gap-2"> <IconCircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" className={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div>
<div className="space-y-3"> <div className="text-muted-foreground text-sm font-medium">Medium (md)</div> <NavigationMenu size="md" aria-label="Medium documentation navigation"> <NavigationMenuList> <NavigationMenuItem value="medium-getting-started"> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuContent> <ul className="w-108"> <li> <NavigationMenuLink href="/docs/getting-started/introduction/"> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">Introduction</div> <div className="text-muted-foreground line-clamp-2"> Reusable components built with Tailwind CSS. </div> </div> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="medium-components" className="hidden md:flex"> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[500px] gap-2 md:w-[600px] md:grid-cols-2 lg:w-[700px]"> {componentLinks.map((component) => ( <li key={component.href}> <NavigationMenuLink href={component.href}> <div className="flex flex-col gap-1.5"> <div className="leading-none font-medium">{component.title}</div> <div className="text-muted-foreground line-clamp-2"> {component.description} </div> </div> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem value="medium-status"> <NavigationMenuTrigger>With icon</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[240px]"> <li> <NavigationMenuLink href="#medium-backlog" className="flex-row items-center gap-2"> <IconAlertCircle />Backlog </NavigationMenuLink> <NavigationMenuLink href="#medium-to-do" className="flex-row items-center gap-2"> <IconCircleDashed />To Do </NavigationMenuLink> <NavigationMenuLink href="#medium-done" className="flex-row items-center gap-2"> <IconCircleCheck />Done </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/docs/" className={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> </div> </div> );}Custom triggers
Native NavigationMenuTrigger elements merge ordinary class customization through their full recipe. With asChild, the child instead owns its complete appearance and markup; Navigation Menu adds behavior, accessibility/state attributes, and the Trigger’s consumer-provided class.
API Reference
Styled Component API
These props are added or materially changed by the installed styled component. Standard HTML attributes remain available through the inherited interfaces noted below. Expand a prop to see named type definitions and framework-specific imports. Follow the Primitive and Runtime links for lower-level behavior props.
Navigation Menu
Inherits nav attributes. Omits `defaultValue`, `onChange`, and `value`.
Contains the following additional props:
"start" | "center" | "end" "start"
- Description
- Aligns the component within its available axis.
- Classification
- Wrapper prop
number 0
- Description
- Offsets the component from its selected alignment in pixels.
- Classification
- Wrapper prop
boolean true
- Description
- Repositions floating content to keep it inside the collision boundary.
- Classification
- Wrapper prop
number 8
- Description
- Sets the minimum space retained around a collision boundary.
- Classification
- Wrapper prop
"sm" | "md" size
- Description
- Sets the independently portaled popup content size and defaults to the resolved Navigation Menu size.
- Classification
- Wrapper prop
boolean false
- Description
- Keeps the public Portal wrapper inline instead of moving it to a target.
- Classification
- Wrapper prop
string —
- Description
- Sets the CSS selector for the public Portal wrapper target.
- Classification
- Wrapper prop
"top" | "right" | "bottom" | "left" "bottom"
- Description
- Selects the preferred side for floating content.
- Classification
- Wrapper prop
number 8
- Description
- Sets the distance in pixels between floating content and its anchor.
- Classification
- Wrapper prop
"sm" | "md" "md"
- Description
- Sets the visual size of native styled triggers, List spacing, indicators, and top-level Links using navigationMenuTriggerStyle().
- Classification
- Wrapper prop
Navigation Menu Item
Inherits li attributes.
Contains the following additional props:
string —
- Description
- Controls or identifies the component value.
- Classification
- Wrapper prop
Navigation Menu Trigger
Inherits button attributes.
Contains the following additional props:
boolean false
- Description
- Delegates markup and complete visual ownership to the child while retaining Navigation Menu behavior and accessibility wiring.
- Classification
- Primitive override
- Primitive prop
- navigation-menu.Trigger.asChild
number —
- Description
- Sets the delay in milliseconds before closing.
- Classification
- Primitive override
- Primitive prop
- navigation-menu.Trigger.closeDelay
string —
- Description
- Adds classes to the component's generated icon.
- Classification
- Wrapper prop
number —
- Description
- Sets the delay in milliseconds before opening.
- Classification
- Primitive override
- Primitive prop
- navigation-menu.Trigger.openDelay
boolean true
- Description
- Shows the component's generated icon.
- Classification
- Wrapper prop
Navigation Menu Positioner
Inherits div attributes.
Contains the following additional props:
boolean false
- Description
- Keeps the public Portal wrapper inline instead of moving it to a target.
- Classification
- Wrapper prop
string —
- Description
- Sets the CSS selector for the public Portal wrapper target.
- Classification
- Wrapper prop
number 8
- Description
- Sets the distance in pixels between floating content and its anchor.
- Classification
- Primitive override
- Primitive prop
- navigation-menu.Positioner.sideOffset
"sm" | "md" "md"
- Description
- Sets the popup content size when rendering NavigationMenuPositioner directly.
- Classification
- Wrapper prop
Primitive And Runtime API
Use these references when you need the lower-level behavior APIs behind Navigation Menu.
Primitive API
Runtime API
- Navigation Menu primitive
createNavigationMenufrom@starwind-ui/runtime/navigation-menu
Changelog
View version history v1.2.0 4 releases
v1.2.0
- Added
portalContaineranddisablePortaltoNavigationMenuandNavigationMenuPositionerfor custom portal targets and inline rendering.
v1.1.1
- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.
v1.1.0
- Added root
smandmdsizing plus independentcontentSizecontrol for the shared portaled popup. OmittedcontentSizefollows the resolved rootsize. - Corrected styled
NavigationMenuTrigger asChildownership: the composed child now keeps its own complete appearance and markup. Style and size the child directly, and add any desired icon inside it; Navigation Menu still supplies behavior and accessibility wiring.
v1.0.0
- Added the Runtime-backed Navigation Menu with keyboard navigation and shared viewport behavior.
- See the Navigation Menu Primitive for the underlying unstyled anatomy and behavior API.