Docs
Mega Menu

Mega Menu

A large, multi-column dropdown navigation with icons, descriptions, categories, and featured content. Perfect for complex site structures and enterprise applications.

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.

3
Mega Menus
9
Categories
27
Menu Items
1
Featured Section

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",
            }}
        />
    );
}
<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

PropTypeDefaultDescription
logoReactNodeundefinedCustom logo component
logoTextstring"Brand"Logo text
links(NavLink | MegaMenuDropdown)[][]Navigation links
ctaButtonCTAButtonundefinedPrimary CTA button
secondaryButtonSecondaryButtonundefinedSecondary button

MegaMenuDropdown

PropTypeDefaultDescription
labelstringRequiredDropdown label
categoriesMegaMenuCategory[]RequiredMenu categories
featuredFeaturedSectionundefinedOptional featured content

MegaMenuCategory

PropTypeDefaultDescription
titlestringRequiredCategory title
itemsMegaMenuItem[]RequiredCategory items

MegaMenuItem

PropTypeDefaultDescription
labelstringRequiredItem label
hrefstringRequiredItem URL
descriptionstringundefinedItem description
iconLucideIconundefinedItem icon
badgestringundefinedOptional badge

FeaturedSection

PropTypeDefaultDescription
titlestringRequiredFeatured title
descriptionstringRequiredFeatured description
hrefstringRequiredFeatured URL
imagestringundefinedOptional 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