Docs
Header Navbar

Header Navbar

A modern, responsive navigation bar with dropdown menus, mobile support, and sticky positioning. Clean solid design with smooth animations and hover effects.

Welcome to Acme Inc

This demo showcases all navbar features: dropdowns, badges, sticky positioning, and responsive mobile menu.

✓ Sticky Header
✓ Dropdown Menus
✓ Badge Support
✓ Mobile Responsive

Section 1

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 2

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 3

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 4

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 5

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 6

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 7

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 8

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 9

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Section 10

Scroll down to see the sticky header behavior. The navbar stays at the top with a solid background and shadow for better visibility.

Features

  • Sticky positioning - Stays at top while scrolling
  • Solid design - Clean solid colors with shadows
  • Dropdown menus - Hover dropdowns on desktop
  • Mobile responsive - Hamburger menu for mobile
  • Badge support - Add "New", "Beta", or custom badges to links
  • CTA buttons - Primary and secondary action buttons
  • Custom logo - Support for logo image or text
  • Underline animation - Smooth underline on hover
  • 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 } from "lucide-react";
import { useState } from "react";
 
interface NavLink {
  label: string;
  href: string;
  badge?: string;
}
 
interface NavDropdown {
  label: string;
  items: NavLink[];
}
 
interface HeaderNavbarProps {
  logo?: React.ReactNode;
  logoText?: string;
  links?: (NavLink | NavDropdown)[];
  ctaButton?: {
    label: string;
    href: string;
    variant?: "primary" | "secondary";
  };
  secondaryButton?: {
    label: string;
    href: string;
  };
}
 
const isDropdown = (item: NavLink | NavDropdown): item is NavDropdown => {
  return "items" in item;
};
 
export function HeaderNavbar({
  logo,
  logoText = "Brand",
  links = [],
  ctaButton,
  secondaryButton,
}: HeaderNavbarProps) {
  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 (isDropdown(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-0 top-full pt-3">
                        <div className="min-w-[220px] rounded-xl border border-zinc-800 bg-zinc-900 p-2 shadow-2xl">
                          {item.items.map((subItem, subIndex) => (
                            <a
                              key={subIndex}
                              href={subItem.href}
                              className="flex items-center justify-between rounded-lg px-4 py-3 text-sm text-zinc-300 transition-all hover:bg-zinc-800 hover:text-white"
                            >
                              <span className="font-medium">
                                {subItem.label}
                              </span>
                              {subItem.badge && (
                                <span className="rounded-full bg-blue-500 px-2.5 py-0.5 text-xs font-semibold text-white">
                                  {subItem.badge}
                                </span>
                              )}
                            </a>
                          ))}
                        </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 (isDropdown(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-1 border-l border-zinc-800 pl-4">
                          {item.items.map((subItem, subIndex) => (
                            <a
                              key={subIndex}
                              href={subItem.href}
                              className="flex items-center justify-between rounded-lg px-4 py-2 text-sm text-zinc-400 transition-colors hover:bg-zinc-900 hover:text-white"
                            >
                              <span>{subItem.label}</span>
                              {subItem.badge && (
                                <span className="rounded-full bg-blue-500/10 px-2 py-0.5 text-xs font-medium text-blue-400">
                                  {subItem.badge}
                                </span>
                              )}
                            </a>
                          ))}
                        </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>
  );
}

Usage

Basic Usage

import HeaderNavbar from "@/components/ui/header-navbar";
 
export default function Page() {
    return (
        <HeaderNavbar
            logoText="Brand"
            links={[
                { label: "Home", href: "/" },
                { label: "About", href: "/about" },
                { label: "Pricing", href: "/pricing" },
            ]}
            ctaButton={{
                label: "Get Started",
                href: "/signup",
            }}
        />
    );
}

With Dropdown Menus

<HeaderNavbar
    logoText="Acme Inc"
    links={[
        { label: "Home", href: "/" },
        {
            label: "Products",
            items: [
                { label: "Analytics", href: "/products/analytics" },
                { label: "Marketing", href: "/products/marketing" },
                { label: "Commerce", href: "/products/commerce" },
            ],
        },
        { label: "Pricing", href: "/pricing" },
    ]}
    ctaButton={{
        label: "Get Started",
        href: "/signup",
    }}
/>

With Badges

<HeaderNavbar
    logoText="Brand"
    links={[
        { label: "Home", href: "/" },
        { label: "Features", href: "/features", badge: "New" },
        {
            label: "Products",
            items: [
                { label: "Analytics", href: "/analytics" },
                { label: "AI Tools", href: "/ai", badge: "Beta" },
            ],
        },
    ]}
/>
<HeaderNavbar
    logo={
        <img
            src="/logo.svg"
            alt="Logo"
            className="h-8 w-8"
        />
    }
    logoText="Company"
    links={[...]}
/>

With Secondary Button

<HeaderNavbar
    logoText="Brand"
    links={[...]}
    secondaryButton={{
        label: "Sign In",
        href: "/signin",
    }}
    ctaButton={{
        label: "Get Started",
        href: "/signup",
    }}
/>

Secondary CTA Variant

<HeaderNavbar
    logoText="Brand"
    links={[...]}
    ctaButton={{
        label: "Contact Sales",
        href: "/contact",
        variant: "secondary", // Outlined style
    }}
/>

Props

HeaderNavbarProps

PropTypeDefaultDescription
logoReactNodeundefinedCustom logo component
logoTextstring"Brand"Logo text
links(NavLink | NavDropdown)[][]Navigation links
ctaButtonCTAButtonundefinedPrimary CTA button
secondaryButtonSecondaryButtonundefinedSecondary button
PropTypeDefaultDescription
labelstringRequiredLink text
hrefstringRequiredLink URL
badgestringundefinedOptional badge text
PropTypeDefaultDescription
labelstringRequiredDropdown label
itemsNavLink[]RequiredDropdown items

CTAButton

PropTypeDefaultDescription
labelstringRequiredButton text
hrefstringRequiredButton URL
variant"primary" | "secondary""primary"Button style

TypeScript Interface

interface HeaderNavbarProps {
    logo?: React.ReactNode;
    logoText?: string;
    links?: (NavLink | NavDropdown)[];
    ctaButton?: {
        label: string;
        href: string;
        variant?: "primary" | "secondary";
    };
    secondaryButton?: {
        label: string;
        href: string;
    };
}
 
interface NavLink {
    label: string;
    href: string;
    badge?: string;
}
 
interface NavDropdown {
    label: string;
    items: NavLink[];
}

Styling

The navbar uses:

  • Sticky positioning - sticky top-0 with shadow
  • Solid colors - bg-zinc-950 with solid borders
  • Dark theme - Zinc-950 background with zinc-800 borders
  • Blue CTA - Solid blue-600 button with hover effects
  • Underline animation - Blue underline on nav link hover
  • Smooth transitions - All hover states animated
  • Shadow effects - Subtle shadows on logo and buttons

Responsive Behavior

  • Desktop (lg+): Horizontal menu with hover dropdowns
  • Mobile: Hamburger menu with expandable sections
  • Tablet: Adapts based on screen size

Accessibility

  • Keyboard navigation support
  • ARIA labels on interactive elements
  • Focus states on all clickable items
  • Semantic HTML structure

Use Cases

Perfect for:

  • SaaS application headers
  • Marketing website navigation
  • Product landing pages
  • Documentation sites
  • E-commerce platforms
  • Portfolio websites
  • Corporate websites
  • Startup landing pages