Mega Menu Navigation
Hover over "Products", "Solutions", or "Resources" to see the mega menu in action. Features multi-column layouts, icons, descriptions, and featured content.
Section 1
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 2
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 3
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 4
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 5
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 6
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 7
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Section 8
Scroll to see the sticky header behavior. The mega menu provides a comprehensive navigation experience with organized categories, icons, and descriptions.
Features
- ✅ Multi-column layout - Up to 4 columns with categories
- ✅ Icons & descriptions - Visual icons with helpful descriptions
- ✅ Featured section - Highlight special content or announcements
- ✅ Badge support - Add "New", "Beta", or custom badges
- ✅ Sticky positioning - Stays at top while scrolling
- ✅ Mobile responsive - Collapsible accordion on mobile
- ✅ Hover activation - Opens on hover for desktop
- ✅ Smooth animations - Transitions and hover effects
- ✅ TypeScript support - Full type safety
- ✅ Accessible - Keyboard navigation and ARIA labels
Installation
Copy and paste the following code into your project.
import { Menu, X, ChevronDown, LucideIcon } from "lucide-react";
import { useState } from "react";
interface MegaMenuItem {
label: string;
href: string;
description?: string;
icon?: LucideIcon;
badge?: string;
}
interface MegaMenuCategory {
title: string;
items: MegaMenuItem[];
}
interface NavLink {
label: string;
href: string;
badge?: string;
}
interface MegaMenuDropdown {
label: string;
categories: MegaMenuCategory[];
featured?: {
title: string;
description: string;
href: string;
image?: string;
};
}
interface MegaMenuProps {
logo?: React.ReactNode;
logoText?: string;
links?: (NavLink | MegaMenuDropdown)[];
ctaButton?: {
label: string;
href: string;
variant?: "primary" | "secondary";
};
secondaryButton?: {
label: string;
href: string;
};
}
const isMegaMenu = (
item: NavLink | MegaMenuDropdown,
): item is MegaMenuDropdown => {
return "categories" in item;
};
export function MegaMenu({
logo,
logoText = "Brand",
links = [],
ctaButton,
secondaryButton,
}: MegaMenuProps) {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [openDropdown, setOpenDropdown] = useState<string | null>(null);
return (
<header className="sticky top-0 z-50 w-full border-b border-zinc-800 bg-zinc-950 shadow-lg">
<nav className="container mx-auto px-4 md:px-6">
<div className="flex h-16 items-center justify-between">
{/* Logo */}
<a
href="/"
className="flex items-center gap-3 transition-transform hover:scale-105"
>
{logo || (
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-blue-600 shadow-lg shadow-blue-600/30">
<span className="text-base font-bold text-white">
{logoText.charAt(0)}
</span>
</div>
)}
<span className="text-xl font-bold text-white">{logoText}</span>
</a>
{/* Desktop Navigation */}
<div className="hidden items-center gap-8 lg:flex">
{links.map((item, index) => {
if (isMegaMenu(item)) {
return (
<div
key={index}
className="group relative"
onMouseEnter={() => setOpenDropdown(item.label)}
onMouseLeave={() => setOpenDropdown(null)}
>
<button className="flex items-center gap-1.5 text-sm font-medium text-zinc-300 transition-colors hover:text-white">
{item.label}
<ChevronDown className="h-4 w-4 transition-transform duration-200 group-hover:rotate-180" />
</button>
{openDropdown === item.label && (
<div className="absolute left-1/2 top-full -translate-x-1/2 pt-3">
<div className="w-max rounded-2xl border border-zinc-800 bg-zinc-900 p-6 shadow-2xl">
<div
className="grid gap-6"
style={{
gridTemplateColumns: `repeat(${item.categories.length + (item.featured ? 1 : 0)}, minmax(240px, 280px))`,
}}
>
{/* Categories */}
{item.categories.map((category, catIndex) => (
<div key={catIndex}>
<h3 className="mb-3 text-xs font-semibold uppercase tracking-wider text-zinc-500">
{category.title}
</h3>
<div className="space-y-1">
{category.items.map((menuItem, itemIndex) => {
const Icon = menuItem.icon;
return (
<a
key={itemIndex}
href={menuItem.href}
className="group/item flex items-start gap-3 rounded-lg p-3 transition-all hover:bg-zinc-800"
>
{Icon && (
<div className="mt-0.5 rounded-lg bg-blue-500/10 p-2">
<Icon className="h-4 w-4 text-blue-400" />
</div>
)}
<div className="flex-1">
<div className="flex items-center gap-2">
<span className="text-sm font-medium text-zinc-300 group-hover/item:text-white">
{menuItem.label}
</span>
{menuItem.badge && (
<span className="rounded-full bg-blue-500 px-2 py-0.5 text-xs font-semibold text-white">
{menuItem.badge}
</span>
)}
</div>
{menuItem.description && (
<p className="mt-0.5 text-xs text-zinc-500">
{menuItem.description}
</p>
)}
</div>
</a>
);
})}
</div>
</div>
))}
{/* Featured Section */}
{item.featured && (
<div className="rounded-xl border border-zinc-800 bg-zinc-950 p-4">
{item.featured.image && (
<div className="mb-3 aspect-video overflow-hidden rounded-lg bg-zinc-800">
<img
src={item.featured.image}
alt={item.featured.title}
className="h-full w-full object-cover"
/>
</div>
)}
<h4 className="font-semibold text-white">
{item.featured.title}
</h4>
<p className="mt-1 text-xs text-zinc-500">
{item.featured.description}
</p>
<a
href={item.featured.href}
className="mt-3 inline-flex items-center text-sm font-medium text-blue-400 hover:text-blue-300"
>
Learn more →
</a>
</div>
)}
</div>
</div>
</div>
)}
</div>
);
}
return (
<a
key={index}
href={item.href}
className="group relative text-sm font-medium text-zinc-300 transition-colors hover:text-white"
>
<span className="relative">
{item.label}
<span className="absolute -bottom-1 left-0 h-0.5 w-0 bg-blue-500 transition-all duration-300 group-hover:w-full" />
</span>
{item.badge && (
<span className="ml-2 rounded-full bg-blue-500 px-2.5 py-0.5 text-xs font-semibold text-white">
{item.badge}
</span>
)}
</a>
);
})}
</div>
{/* Desktop CTA Buttons */}
<div className="hidden items-center gap-4 lg:flex">
{secondaryButton && (
<a
href={secondaryButton.href}
className="rounded-lg px-5 py-2.5 text-sm font-semibold text-zinc-300 transition-all hover:text-white"
>
{secondaryButton.label}
</a>
)}
{ctaButton && (
<a
href={ctaButton.href}
className={`rounded-lg px-5 py-2.5 text-sm font-semibold shadow-lg transition-all ${
ctaButton.variant === "secondary"
? "border-2 border-zinc-700 bg-zinc-800 text-white hover:border-zinc-600 hover:bg-zinc-700"
: "bg-blue-600 text-white shadow-blue-600/30 hover:bg-blue-500 hover:shadow-blue-600/50"
}`}
>
{ctaButton.label}
</a>
)}
</div>
{/* Mobile Menu Button */}
<button
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
className="rounded-lg bg-zinc-900 p-2.5 text-zinc-300 transition-all hover:bg-zinc-800 hover:text-white lg:hidden"
aria-label="Toggle menu"
>
{mobileMenuOpen ? (
<X className="h-5 w-5" />
) : (
<Menu className="h-5 w-5" />
)}
</button>
</div>
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="border-t border-zinc-800 bg-zinc-900/50 py-4 lg:hidden">
<div className="space-y-1">
{links.map((item, index) => {
if (isMegaMenu(item)) {
return (
<div key={index} className="space-y-1">
<button
onClick={() =>
setOpenDropdown(
openDropdown === item.label ? null : item.label,
)
}
className="flex w-full items-center justify-between rounded-lg px-4 py-2.5 text-sm font-medium text-zinc-400 transition-colors hover:bg-zinc-900 hover:text-white"
>
{item.label}
<ChevronDown
className={`h-4 w-4 transition-transform ${
openDropdown === item.label ? "rotate-180" : ""
}`}
/>
</button>
{openDropdown === item.label && (
<div className="ml-4 space-y-3 border-l border-zinc-800 pl-4">
{item.categories.map((category, catIndex) => (
<div key={catIndex}>
<h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-zinc-600">
{category.title}
</h4>
<div className="space-y-1">
{category.items.map((menuItem, itemIndex) => (
<a
key={itemIndex}
href={menuItem.href}
className="flex items-center justify-between rounded-lg px-3 py-2 text-sm text-zinc-400 transition-colors hover:bg-zinc-900 hover:text-white"
>
<span>{menuItem.label}</span>
{menuItem.badge && (
<span className="rounded-full bg-blue-500/10 px-2 py-0.5 text-xs font-medium text-blue-400">
{menuItem.badge}
</span>
)}
</a>
))}
</div>
</div>
))}
</div>
)}
</div>
);
}
return (
<a
key={index}
href={item.href}
className="flex items-center justify-between rounded-lg px-4 py-2.5 text-sm font-medium text-zinc-400 transition-colors hover:bg-zinc-900 hover:text-white"
>
<span>{item.label}</span>
{item.badge && (
<span className="rounded-full bg-blue-500/10 px-2 py-0.5 text-xs font-medium text-blue-400">
{item.badge}
</span>
)}
</a>
);
})}
</div>
{/* Mobile CTA Buttons */}
<div className="mt-4 space-y-3 border-t border-zinc-800 pt-4">
{secondaryButton && (
<a
href={secondaryButton.href}
className="block rounded-lg border-2 border-zinc-700 bg-zinc-800 px-4 py-3 text-center text-sm font-semibold text-white transition-all hover:border-zinc-600 hover:bg-zinc-700"
>
{secondaryButton.label}
</a>
)}
{ctaButton && (
<a
href={ctaButton.href}
className="block rounded-lg bg-blue-600 px-4 py-3 text-center text-sm font-semibold text-white shadow-lg shadow-blue-600/30 transition-all hover:bg-blue-500 hover:shadow-blue-600/50"
>
{ctaButton.label}
</a>
)}
</div>
</div>
)}
</nav>
</header>
);
}Update the import paths to match your project setup.
Usage
Basic Usage
import MegaMenu from "@/components/ui/mega-menu";
import { BarChart3, Users, Code } from "lucide-react";
export default function Page() {
return (
<MegaMenu
logoText="Brand"
links={[
{ label: "Home", href: "/" },
{
label: "Products",
categories: [
{
title: "Analytics",
items: [
{
label: "Business Intelligence",
href: "/products/bi",
description: "Real-time data visualization",
icon: BarChart3,
},
{
label: "Customer Analytics",
href: "/products/customer",
description: "Understand your users",
icon: Users,
},
],
},
],
},
{ label: "Pricing", href: "/pricing" },
]}
ctaButton={{
label: "Get Started",
href: "/signup",
}}
/>
);
}With Featured Section
<MegaMenu
logoText="Brand"
links={[
{
label: "Products",
categories: [
{
title: "Tools",
items: [
{
label: "API Platform",
href: "/api",
description: "RESTful APIs",
icon: Code,
},
],
},
],
featured: {
title: "New: AI-Powered Analytics",
description: "Get instant insights with our new AI engine.",
href: "/products/ai",
},
},
]}
/>With Badges
<MegaMenu
links={[
{
label: "Products",
categories: [
{
title: "New Features",
items: [
{
label: "AI Tools",
href: "/ai",
description: "Powered by machine learning",
icon: Zap,
badge: "New",
},
{
label: "Beta Features",
href: "/beta",
description: "Try our latest features",
icon: Code,
badge: "Beta",
},
],
},
],
},
]}
/>Multiple Categories
<MegaMenu
links={[
{
label: "Products",
categories: [
{
title: "Analytics",
items: [
{ label: "BI", href: "/bi", icon: BarChart3 },
{ label: "Reports", href: "/reports", icon: FileText },
],
},
{
title: "Infrastructure",
items: [
{ label: "Cloud", href: "/cloud", icon: Cloud },
{ label: "Database", href: "/db", icon: Database },
],
},
{
title: "Developer",
items: [
{ label: "API", href: "/api", icon: Code },
{ label: "SDK", href: "/sdk", icon: Package },
],
},
],
},
]}
/>Props
MegaMenuProps
| Prop | Type | Default | Description |
|---|---|---|---|
logo | ReactNode | undefined | Custom logo component |
logoText | string | "Brand" | Logo text |
links | (NavLink | MegaMenuDropdown)[] | [] | Navigation links |
ctaButton | CTAButton | undefined | Primary CTA button |
secondaryButton | SecondaryButton | undefined | Secondary button |
MegaMenuDropdown
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | Required | Dropdown label |
categories | MegaMenuCategory[] | Required | Menu categories |
featured | FeaturedSection | undefined | Optional featured content |
MegaMenuCategory
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | Required | Category title |
items | MegaMenuItem[] | Required | Category items |
MegaMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | Required | Item label |
href | string | Required | Item URL |
description | string | undefined | Item description |
icon | LucideIcon | undefined | Item icon |
badge | string | undefined | Optional badge |
FeaturedSection
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | Required | Featured title |
description | string | Required | Featured description |
href | string | Required | Featured URL |
image | string | undefined | Optional image URL |
TypeScript Interface
interface MegaMenuProps {
logo?: React.ReactNode;
logoText?: string;
links?: (NavLink | MegaMenuDropdown)[];
ctaButton?: {
label: string;
href: string;
variant?: "primary" | "secondary";
};
secondaryButton?: {
label: string;
href: string;
};
}
interface MegaMenuDropdown {
label: string;
categories: MegaMenuCategory[];
featured?: {
title: string;
description: string;
href: string;
image?: string;
};
}
interface MegaMenuCategory {
title: string;
items: MegaMenuItem[];
}
interface MegaMenuItem {
label: string;
href: string;
description?: string;
icon?: LucideIcon;
badge?: string;
}Layout
The mega menu supports up to 4 columns:
- 3 categories: Each takes 1 column
- 3 categories + featured: 3 columns for categories, 1 for featured
- Responsive: Stacks on mobile with accordion behavior
Styling
- Solid colors - Clean zinc-900 background
- Icons - Blue icon backgrounds with hover effects
- Shadows - Subtle shadows for depth
- Animations - Smooth transitions on hover
- Typography - Clear hierarchy with descriptions
Responsive Behavior
- Desktop (lg+): Multi-column mega menu on hover
- Mobile: Accordion-style expandable sections
- Tablet: Adapts based on screen size
Use Cases
Perfect for:
- Enterprise websites
- SaaS platforms with many products
- E-commerce sites with categories
- Documentation sites
- Large corporate websites
- Product portfolios
- Service marketplaces
- Complex site structures