Header
Headers are a great way to provide navigation and branding to your users.
Basic Header
import React, { useState } from "react";
import { Menu, X } from "lucide-react";
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<nav className="bg-white dark:bg-black border-b border-neutral-200 dark:border-neutral-800">
<div className="container mx-auto px-6">
<div className="flex h-16 items-center justify-between">
<div className="text-lg font-medium text-neutral-900 dark:text-white">
Logo
</div>
<button
className="text-neutral-900 dark:text-white md:hidden z-20"
onClick={() => setIsOpen(!isOpen)}
aria-label="Toggle menu"
>
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
<div
className={`fixed inset-0 bg-white dark:bg-black bg-opacity-90 dark:bg-opacity-90 z-10 transition-all duration-500
${
isOpen
? "opacity-100 translate-x-0"
: "opacity-0 translate-x-full pointer-events-none"
}
md:relative md:inset-auto md:bg-transparent md:dark:bg-transparent md:translate-x-0 md:opacity-100 md:pointer-events-auto`}
>
<div className="flex flex-col h-full justify-center items-center space-y-8 md:space-y-0 md:flex-row md:items-center md:space-x-8">
{["Home", "About", "Services", "Contact"].map((item) => (
<a
key={item}
href="#"
className="text-xl md:text-sm text-neutral-900 dark:text-white hover:text-neutral-500 dark:hover:text-neutral-400 transition-colors duration-300"
onClick={() => setIsOpen(false)}
>
{item}
</a>
))}
</div>
</div>
</div>
</div>
</nav>
);
};
export default Header;
Header with Search
import React, { useState } from "react";
import { Menu, Search, User, X } from "lucide-react";
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<nav className="bg-white dark:bg-black border-b border-neutral-200 dark:border-neutral-800">
<div className="container mx-auto px-6">
<div className="flex h-16 items-center justify-between">
<div className="text-lg font-medium text-neutral-900 dark:text-white">
Logo
</div>
<div className="flex items-center space-x-6">
<div className="relative hidden md:block">
<input
type="text"
className="w-64 rounded-xl bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-white px-4 py-2 text-sm focus:outline-none placeholder:text-neutral-400"
placeholder="Search..."
/>
<button className="absolute right-3 top-1/2 -translate-y-1/2">
<Search className="w-4 h-4 text-neutral-400 hover:text-neutral-900 dark:hover:text-white transition-colors duration-300" />
</button>
</div>
<button className="text-neutral-900 dark:text-white hover:text-neutral-500 dark:hover:text-neutral-400 transition-colors duration-300">
<User className="w-6 h-6" />
</button>
<button
className="text-neutral-900 dark:text-white md:hidden"
onClick={() => setIsOpen(!isOpen)}
aria-label="Toggle menu"
>
{isOpen ? (
<X className="w-6 h-6" />
) : (
<Menu className="w-6 h-6" />
)}
</button>
</div>
</div>
<div
className={`overflow-hidden transition-all duration-300 ${
isOpen ? "max-h-24 opacity-100" : "max-h-0 opacity-0"
} md:hidden`}
>
<div className="py-4">
<input
type="text"
className="w-full rounded-xl bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-white px-4 py-2 text-sm focus:outline-none placeholder:text-neutral-400"
placeholder="Search..."
/>
</div>
</div>
</div>
</nav>
);
};
export default Header;
Header with Animated Underline
import React, { useState } from "react";
import { Menu, X } from "lucide-react";
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<nav className="bg-white dark:bg-black border-b border-neutral-200 dark:border-neutral-800">
<div className="container mx-auto px-6">
<div className="flex h-16 items-center justify-between">
<div className="text-lg font-medium text-neutral-900 dark:text-white">
Logo
</div>
<button
className="text-neutral-900 dark:text-white md:hidden z-20"
onClick={() => setIsOpen(!isOpen)}
aria-label="Toggle menu"
>
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
<div
className={`fixed inset-0 bg-white dark:bg-black bg-opacity-90 dark:bg-opacity-90 z-10 transition-all duration-500
${
isOpen
? "opacity-100 translate-x-0"
: "opacity-0 translate-x-full pointer-events-none"
}
md:relative md:inset-auto md:bg-transparent md:dark:bg-transparent md:translate-x-0 md:opacity-100 md:pointer-events-auto`}
>
<div className="flex flex-col h-full justify-center items-center space-y-8 md:space-y-0 md:flex-row md:items-center md:space-x-8">
{["Home", "About", "Services", "Contact"].map((item) => (
<a
key={item}
href="#"
className="text-xl md:text-sm text-neutral-900 dark:text-white transition-all duration-300
relative after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:origin-center after:scale-x-0
after:bg-neutral-900 dark:after:bg-white after:transition-transform after:duration-300
hover:after:scale-x-100"
onClick={() => setIsOpen(false)}
>
{item}
</a>
))}
</div>
</div>
</div>
</div>
</nav>
);
};
export default Header;
Centered Aligned Header
import React, { useState } from "react";
import { Menu, X } from "lucide-react";
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
const navItems = ["Home", "About", "Services", "Contact"];
const handleClickOutside = (e: any) => {
if (isOpen && !e.target.closest("nav")) {
setIsOpen(false);
}
};
React.useEffect(() => {
document.addEventListener("click", handleClickOutside);
return () => document.removeEventListener("click", handleClickOutside);
}, [isOpen]);
return (
<nav className="fixed top-0 left-0 right-0 z-50 bg-white dark:bg-black border-b border-neutral-200 dark:border-neutral-800">
<div className="container mx-auto px-4">
<div className="flex h-16 items-center justify-between">
<div className="text-lg font-medium text-neutral-900 dark:text-white">
Logo
</div>
<button
className="relative z-50 text-neutral-900 dark:text-white md:hidden"
onClick={(e) => {
e.stopPropagation();
setIsOpen(!isOpen);
}}
aria-label="Toggle menu"
>
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
<div className="hidden md:flex items-center space-x-8">
{navItems.map((item) => (
<a
key={item}
href="#"
className="text-sm text-neutral-900 dark:text-white hover:text-neutral-500 dark:hover:text-neutral-400 transition-colors duration-300"
>
{item}
</a>
))}
</div>
<div className="hidden md:flex items-center space-x-4">
<a
href="#"
className="rounded-full bg-neutral-900 px-6 py-2 text-sm font-medium text-white hover:bg-neutral-700 dark:bg-white dark:text-neutral-900 dark:hover:bg-neutral-100 transition-colors duration-300"
>
Sign Up
</a>
<a
href="#"
className="px-6 py-2 text-sm font-medium text-neutral-900 hover:text-neutral-500 dark:text-white dark:hover:text-neutral-400 transition-colors duration-300"
>
Login
</a>
</div>
</div>
</div>
<div
className={`fixed inset-0 bg-black bg-opacity-50 transition-opacity duration-300 md:hidden ${
isOpen ? "opacity-100" : "opacity-0 pointer-events-none"
}`}
>
<div
className={`absolute right-0 top-16 h-screen w-64 bg-white dark:bg-black transform transition-transform duration-300 ease-in-out ${
isOpen ? "translate-x-0" : "translate-x-full"
}`}
>
<div className="flex flex-col p-4">
<div className="flex flex-col space-y-4 mb-8">
{navItems.map((item) => (
<a
key={item}
href="#"
className="text-sm text-neutral-900 dark:text-white hover:text-neutral-500 dark:hover:text-neutral-400 transition-colors duration-300"
>
{item}
</a>
))}
</div>
<div className="flex flex-col space-y-4">
<a
href="#"
className="rounded-full bg-neutral-900 px-6 py-2 text-sm font-medium text-white text-center hover:bg-neutral-700 dark:bg-white dark:text-neutral-900 dark:hover:bg-neutral-100 transition-colors duration-300"
>
Sign Up
</a>
<a
href="#"
className="px-6 py-2 text-sm font-medium text-neutral-900 hover:text-neutral-500 dark:text-white dark:hover:text-neutral-400 text-center transition-colors duration-300"
>
Login
</a>
</div>
</div>
</div>
</div>
</nav>
);
};
export default Header;