---
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"
const components = [
{
title: "Alert",
href: "/components/alert/",
description:
"Displays important messages with title and description content.",
},
{
title: "Sheet",
href: "/components/sheet/",
description: "A side panel component built on top of dialog primitives.",
},
{
title: "Native Select",
href: "/components/native-select/",
description:
"A styled native select element for choosing one option from a list.",
},
{
title: "Tabs",
href: "/components/tabs/",
description:
"A set of layered sections of content displayed one at a time.",
},
]
---
<div class="min-h-96 overflow-visible">
<NavigationMenu>
<NavigationMenuList class="flex-wrap gap-1">
<NavigationMenuItem value="getting-started">
<NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
<NavigationMenuContent>
<ul class="w-60 p-1 sm:w-96">
<li>
<NavigationMenuLink
href="/docs"
class="w-full flex-col items-start"
>
<span class="leading-none font-medium">Introduction</span>
<span class="text-muted-foreground line-clamp-2 text-sm">
Re-usable components built with Tailwind CSS.
</span>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink
href="/docs/installation/"
class="w-full flex-col items-start"
>
<span class="leading-none font-medium">Installation</span>
<span class="text-muted-foreground line-clamp-2 text-sm">
How to install dependencies and structure your app.
</span>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink
href="/components/typography/"
class="w-full flex-col items-start"
>
<span class="leading-none font-medium">Typography</span>
<span class="text-muted-foreground line-clamp-2 text-sm">
Styles for headings, paragraphs, lists, and more.
</span>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem value="components" class="hidden md:block">
<NavigationMenuTrigger>Components</NavigationMenuTrigger>
<NavigationMenuContent>
<ul
class="grid w-[400px] gap-2 p-1 md:w-[500px] md:grid-cols-2 lg:w-[600px]"
>
{
components.map((component) => (
<li>
<NavigationMenuLink
href={component.href}
class="w-full flex-col items-start"
>
<span class="leading-none font-medium">
{component.title}
</span>
<span class="text-muted-foreground line-clamp-2 text-sm">
{component.description}
</span>
</NavigationMenuLink>
</li>
))
}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem value="docs">
<NavigationMenuLink href="/docs" class={navigationMenuTriggerStyle()}>
Docs
</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</div>Installation
npx shadcn@latest add @fulldev/navigation-menu
Usage
---
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
---
<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
│ └── NavigationMenuLink
└── NavigationMenuIndicator
Notes
-
Closed panels start hidden in the rendered HTML to prevent a flash before JavaScript initializes. The controller manages visibility after initialization.
-
Place
NavigationMenuIndicatorinsideNavigationMenuListso its position is relative to the list whose measurements Data Slot uses. -
Use
NavigationMenuTriggerfor items that open richer panels andNavigationMenuLinkfor direct navigation targets. -
NavigationMenuLinkacceptsactivewhen the current route should be visually highlighted. -
Keep the content panel layout inside
NavigationMenuContentsimple and list-like so keyboard navigation stays predictable.
The menu opens below its trigger, aligned to the start, with an 8px gap. Set
side, align, sideOffset, and alignOffset on NavigationMenu to change
this placement. Data Slot reads the root configuration and positions the shared
popup.
Content mounting
Data Slot’s recommended "lazy" strategy is the default: closed content is
retained but detached from the document. Fulldev initializes nested Data Slot
components inside that retained content too.
Use mountStrategy="eager" when an integration needs to query closed content
through the document. Both strategies include content in server-rendered HTML;
neither adds a no-JavaScript fallback.
API Reference
See the GitHub source code for more information on props. See the data-slot docs for more information on interactivity.