import React from "react";
import Link from "next/link";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
const components = [
{
title: "Alert Dialog",
href: "/docs/ui/alert-dialog",
description: "Prompts the user for a response before continuing.",
},
{
title: "Preview Card",
href: "/docs/ui/preview-card",
description: "Displays a compact, visually appealing preview of content.",
},
{
title: "Toast",
href: "/docs/ui/progress",
description: "Briefly displays transient messages or notifications.",
},
{
title: "Context Menu",
href: "/docs/ui/context-menu",
description:
"A contextual menu that appears on right-click, showing a list of actions and options in a collapsible panel.",
},
{
title: "Tabs",
href: "/docs/ui/tabs",
description: "Organizes content into switchable panels under tab labels.",
},
{
title: "Menubar",
href: "/docs/ui/menubar",
description:
"A horizontal navigation bar that displays a list of menu items and dropdown menus.",
},
];
export function NavigationMenuDemo() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Home</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-2 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3">
<NavigationMenuLink
render={
<Link
className="from-muted/50 to-muted flex h-full w-full flex-col justify-end rounded-md bg-linear-to-b p-6 no-underline outline-hidden select-none focus:shadow-md"
href="/"
>
<div className="mt-4 mb-2 text-lg font-medium">
eo-n/ui
</div>
<p className="text-muted-foreground text-sm leading-tight">
Accessible and customizable components built with
Tailwind and Shadcn.
</p>
</Link>
}
/>
</li>
<ListItem href="/docs" title="Introduction">
Collection of accessible and customizable UI primitives to build
your own components with ease.
</ListItem>
<ListItem href="/docs/installation" title="Installation">
Learn how to set up dependencies and organize your application
structure.
</ListItem>
<ListItem href="/docs/dark-mode" title="Dark mode">
Learn how to implement and customize dark mode in your
application.
</ListItem>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Components</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-2 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
{components.map((component) => (
<ListItem
key={component.title}
title={component.title}
href={component.href}
>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink
render={
<Link className={navigationMenuTriggerStyle()} href="/docs">
Docs
</Link>
}
/>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
}
function ListItem({
title,
children,
href,
...props
}: React.ComponentPropsWithoutRef<"li"> & { href: string }) {
return (
<li {...props}>
<NavigationMenuLink
render={
<Link href={href} className="flex flex-col gap-2 no-underline">
<div className="text-sm leading-none font-medium">{title}</div>
<p className="text-muted-foreground line-clamp-2 flex text-sm leading-snug">
{children}
</p>
</Link>
}
/>
</li>
);
}
Installation
npx shadcn@latest add "https://eo-n.vercel.app/r/navigation-menu"
Usage
Import all parts and piece them together.
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Menubar } from "@/components/ui/menubar";
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Item One</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Link</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
Examples
Nested Sub Menu
import React from "react";
import Link from "next/link";
import { cn } from "@/lib/utils";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuIcon,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
NavigationSubMenuTrigger,
} from "@/components/ui/navigation-menu";
const products = [
{
title: "Enterprise",
href: "/docs/ui/navigation-menu/#",
description: "Complete solution for large organizations and enterprises.",
},
{
title: "Professional",
href: "/docs/ui/navigation-menu/#",
description: "Advanced features for growing businesses.",
},
{
title: "Starter",
href: "/docs/ui/navigation-menu/#",
description: "Perfect for individuals and small teams.",
},
{
title: "Free",
href: "/docs/ui/navigation-menu/#",
description: "Basic features to get started.",
},
];
export function NavigationMenuNested() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid gap-2 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3">
<NavigationMenuLink
render={
<Link
className="from-muted/50 to-muted flex h-full w-full flex-col justify-end rounded-md bg-linear-to-b p-6 no-underline outline-hidden select-none focus:shadow-md"
href="/docs/ui/navigation-menu/#"
>
<div className="mt-4 mb-2 text-lg font-medium">
Our Products
</div>
<p className="text-muted-foreground text-sm leading-tight">
Discover our range of solutions for your business needs.
</p>
</Link>
}
/>
</li>
{products.slice(0, 2).map((product) => (
<ListItem
key={product.title}
title={product.title}
href={product.href}
>
{product.description}
</ListItem>
))}
<NavigationMenu
contentProps={{
side: "right",
align: "end",
sideOffset: 20,
alignOffset: -17,
}}
>
<NavigationMenuItem>
<NavigationSubMenuTrigger
nativeButton={false}
render={(props, state) => (
<ListItem
href="/docs/ui/navigation-menu/#"
title="Enterprise Solutions"
{...props}
>
Advanced features for large organizations
<NavigationMenuIcon
className={cn("-rotate-90", {
"rotate-90": state.open,
})}
/>
</ListItem>
)}
/>
<NavigationMenuContent>
<ul className="flex h-auto w-full max-w-[400px] min-w-[250px] flex-col gap-2 md:w-[250px]">
{products.slice(2).map((product) => (
<ListItem
key={product.title}
title={product.title}
href={product.href}
>
{product.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenu>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
}
function ListItem({
title,
children,
href,
...props
}: React.ComponentPropsWithoutRef<"li"> & { href: string }) {
return (
<li {...props}>
<NavigationMenuLink
render={
<Link href={href} className="flex flex-col gap-2 no-underline">
<div className="text-sm leading-none font-medium">{title}</div>
<p className="text-muted-foreground line-clamp-2 flex text-sm leading-snug">
{children}
</p>
</Link>
}
/>
</li>
);
}