Navigation menu
The top navigation of a marketing site or docs, with dropdown panels of links that animate between each other.
npx prodular-ui add navigation-menuMarketing header
Panels with an icon, a title and one line per link. Hover Product, then move to Solutions.
import { BarChart3Icon, BotIcon, InboxIcon, PlugIcon, ShieldCheckIcon, WorkflowIcon,} from "lucide-react"
import { Button } from "@/components/ui/button"import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuLinkText, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle,} from "@/components/ui/navigation-menu"
const product = [ { icon: InboxIcon, title: "Shared inbox", description: "Email, chat and forms in one queue." }, { icon: WorkflowIcon, title: "Automations", description: "Route, tag and escalate without code." }, { icon: BotIcon, title: "AI agent", description: "Drafts replies from your help center." }, { icon: BarChart3Icon, title: "Reports", description: "Response times, CSAT and backlog." }, { icon: PlugIcon, title: "Integrations", description: "Slack, Linear, Salesforce and 60 more." }, { icon: ShieldCheckIcon, title: "Security", description: "SSO, audit log and data residency." },]
const solutions = [ { title: "Customer support", description: "For teams answering 1,000+ tickets a week." }, { title: "Customer success", description: "Track health and renewals per account." }, { title: "IT help desk", description: "Internal requests with SLAs and approvals." },]
export default function NavigationMenuMarketing() { return ( <header className="flex w-full max-w-3xl items-center gap-6 self-start rounded-xl border bg-background px-4 py-2.5 shadow-xs"> <span className="text-[15px] font-semibold tracking-tight">Relay</span> <NavigationMenu> <NavigationMenuList> <NavigationMenuItem> <NavigationMenuTrigger>Product</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid gap-0.5 sm:w-xl sm:grid-cols-2"> {product.map((p) => ( <li key={p.title}> <NavigationMenuLink href="#"> <p.icon className="mt-0.5" /> <NavigationMenuLinkText title={p.title} description={p.description} /> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuTrigger>Solutions</NavigationMenuTrigger> <NavigationMenuContent> <ul className="flex flex-col gap-0.5 sm:w-80"> {solutions.map((s) => ( <li key={s.title}> <NavigationMenuLink href="#"> <NavigationMenuLinkText title={s.title} description={s.description} /> </NavigationMenuLink> </li> ))} </ul> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}> Pricing </NavigationMenuLink> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}> Customers </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> <div className="ml-auto flex items-center gap-2"> <Button variant="ghost" size="sm"> Log in </Button> <Button size="sm">Start free trial</Button> </div> </header> )}Plain links
Style links like triggers with navigationMenuTriggerStyle. active marks the current page.
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, navigationMenuTriggerStyle,} from "@/components/ui/navigation-menu"
const links = [ { label: "Overview", active: true }, { label: "Activity", active: false }, { label: "Members", active: false }, { label: "Billing", active: false }, { label: "Settings", active: false },]
export default function NavigationMenuLinks() { return ( <NavigationMenu> <NavigationMenuList> {links.map((l) => ( <NavigationMenuItem key={l.label}> <NavigationMenuLink href="#" active={l.active} aria-current={l.active ? "page" : undefined} className={navigationMenuTriggerStyle()} > {l.label} </NavigationMenuLink> </NavigationMenuItem> ))} </NavigationMenuList> </NavigationMenu> )}Anatomy
<NavigationMenu> <NavigationMenuList> <NavigationMenuItem> <NavigationMenuTrigger>Product</NavigationMenuTrigger> <NavigationMenuContent> <NavigationMenuLink href="/inbox"> <InboxIcon /> <NavigationMenuLinkText title="Shared inbox" description="Email, chat and forms in one queue." /> </NavigationMenuLink> </NavigationMenuContent> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="/pricing" className={navigationMenuTriggerStyle()}>Pricing</NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList></NavigationMenu>Guidance
Use it when
- Use for the header of a marketing site, docs or a public app with a few top level sections.
- Use NavigationMenuLinkText inside links to show a title and one line of description.
Avoid
- In app navigation. Use Sidebar or Tabs.
- More than five or six top level items. Group them into panels.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Every link must be a NavigationMenuLink with a real href. Pass render={<NextLink href="..." />} for client routing.
- Top level links without a panel use className={navigationMenuTriggerStyle()} so they match the triggers.
- Set active and aria-current="page" on the link for the current page.
- Give each NavigationMenuContent list a width with sm:w-* so panels do not jump between sizes.
- Keep descriptions to one short line.
API
NavigationMenu
| Prop | Type | Default | Description |
|---|---|---|---|
| align | "start" | "center" | "end" | "start" | Alignment of the panel against the active trigger. |
| value / onValueChange | string | null | Controls which panel is open. |
NavigationMenuLink
| Prop | Type | Default | Description |
|---|---|---|---|
| active | boolean | false | Marks the current page. |
NavigationMenuLinkText
| Prop | Type | Default | Description |
|---|---|---|---|
| title / description | ReactNode | Title and one line of copy inside a link. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add navigation-menu# or, with the registry in components.jsonnpx shadcn@latest add @prodular/navigation-menu