Files
mozimo.in/src/components/Header.tsx
2025-08-05 00:29:15 +05:30

480 lines
19 KiB
TypeScript

"use client";
import { motion, AnimatePresence } from "framer-motion";
import Image from "next/image";
import { useState, useEffect } from "react";
export default function Header() {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
const scrollPosition = window.scrollY;
setIsScrolled(scrollPosition > 100);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
// Close mobile menu when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const target = event.target as Element;
if (
!target.closest(".mobile-menu") &&
!target.closest(".hamburger-button")
) {
setIsMobileMenuOpen(false);
}
};
if (isMobileMenuOpen) {
document.addEventListener("click", handleClickOutside);
}
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, [isMobileMenuOpen]);
// Prevent body scroll when mobile menu is open
useEffect(() => {
if (isMobileMenuOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "unset";
}
return () => {
document.body.style.overflow = "unset";
};
}, [isMobileMenuOpen]);
const toggleMobileMenu = () => {
setIsMobileMenuOpen(!isMobileMenuOpen);
};
return (
<>
{/* Mobile Header - Only visible on mobile */}
<motion.header
className="fixed top-0 z-[60] w-full md:hidden"
initial={false}
animate={{
width: "100%",
left: "0%",
x: "0%",
top: isScrolled ? "0px" : "12px",
borderRadius: "0px",
height: isScrolled ? "64px" : "60px",
}}
transition={{
duration: 0.5,
ease: [0.25, 0.46, 0.45, 0.94],
}}
>
<nav
className={`bg-white border border-white/20 shadow-premium w-full h-full flex justify-between items-center rounded-none`}
>
<div className="flex justify-between items-center w-full px-4">
{/* Mobile Hamburger Menu */}
<motion.button
className="hamburger-button p-2 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-w-[40px] min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
onClick={toggleMobileMenu}
aria-label="Toggle mobile menu"
>
<div className="w-6 h-6 flex flex-col justify-center items-center">
<motion.span
className="w-6 h-0.5 bg-current block transition-all duration-300"
animate={{
rotate: isMobileMenuOpen ? 45 : 0,
y: isMobileMenuOpen ? 6 : 0,
}}
/>
<motion.span
className="w-6 h-0.5 bg-current block mt-1 transition-all duration-300"
animate={{
opacity: isMobileMenuOpen ? 0 : 1,
}}
/>
<motion.span
className="w-6 h-0.5 bg-current block mt-1 transition-all duration-300"
animate={{
rotate: isMobileMenuOpen ? -45 : 0,
y: isMobileMenuOpen ? -6 : 0,
}}
/>
</div>
</motion.button>
{/* Center Logo */}
<motion.div
className="flex items-center justify-center absolute left-1/2 transform -translate-x-1/2"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<motion.div
className="relative w-10 h-10"
animate={{
scale: isScrolled ? 1.1 : 1,
}}
transition={{ duration: 0.5, ease: "easeInOut" }}
whileHover={{
scale: 1.15,
rotate: 5,
transition: { duration: 0.3 },
}}
>
<Image
src="/logo/logo.svg"
alt="Mozimo Logo"
fill
className="object-contain drop-shadow-lg"
priority
sizes="40px"
quality={95}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWGRkqGx0f/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
/>
</motion.div>
</motion.div>
{/* Mobile Right Side - Empty space to balance layout */}
<div className="w-10 h-10"></div>
</div>
</nav>
</motion.header>
{/* Desktop Header - Only visible on desktop */}
<motion.header
className="fixed top-0 z-50 hidden md:block"
initial={false}
animate={{
width: isScrolled ? "100%" : "1440px",
left: isScrolled ? "0%" : "50%",
x: isScrolled ? "0%" : "-50%",
top: isScrolled ? "0px" : "24px",
borderRadius: isScrolled ? "0px" : "15px",
height: isScrolled ? "64px" : "80px",
}}
transition={{
duration: 0.5,
ease: [0.25, 0.46, 0.45, 0.94],
}}
>
<nav
className={`bg-white border border-white/20 shadow-premium w-full h-full flex justify-between items-center ${
isScrolled ? "rounded-none" : "rounded-[15px]"
}`}
>
<div className="flex justify-between items-center w-full px-20">
{/* Left Navigation */}
<div className="flex items-center space-x-16">
<motion.a
href="#about"
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
style={{
fontWeight: 100,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
whileHover={{ scale: 1.02 }}
>
About us
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-gradient-to-r from-[#8B4513] to-[#DAA520] transition-all duration-300 group-hover:w-full"></span>
</motion.a>
<motion.a
href="#shop"
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
style={{
fontWeight: 100,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
whileHover={{ scale: 1.02 }}
>
Shop
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-gradient-to-r from-[#8B4513] to-[#DAA520] transition-all duration-300 group-hover:w-full"></span>
</motion.a>
</div>
{/* Center Logo */}
<motion.div
className="flex items-center justify-center absolute left-1/2 transform -translate-x-1/2"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<motion.div
className="relative w-12 h-12"
animate={{
scale: isScrolled ? 1.1 : 1,
}}
transition={{ duration: 0.5, ease: "easeInOut" }}
whileHover={{
scale: 1.15,
rotate: 5,
transition: { duration: 0.3 },
}}
>
<Image
src="/logo/logo.svg"
alt="Mozimo Logo"
fill
className="object-contain drop-shadow-lg"
priority
sizes="48px"
quality={95}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWGRkqGx0f/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
/>
</motion.div>
</motion.div>
{/* Right Icons */}
<div className="flex items-center space-x-8">
{/* More Dropdown */}
<motion.button
className="flex items-center space-x-1 text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
style={{
fontWeight: 100,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
whileHover={{ scale: 1.02 }}
aria-label="More options"
>
<span>More</span>
<motion.svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
animate={{ rotate: 0 }}
whileHover={{ rotate: 180 }}
transition={{ duration: 0.3 }}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</motion.svg>
</motion.button>
<motion.button
className="p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-w-[40px] min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm"
whileHover={{ scale: 1.1, rotate: 5 }}
whileTap={{ scale: 0.95 }}
aria-label="User account"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</motion.button>
<motion.button
className="p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-w-[40px] min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm"
whileHover={{ scale: 1.1, rotate: -5 }}
whileTap={{ scale: 0.95 }}
aria-label="Search"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</motion.button>
<motion.button
className="p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-w-[40px] min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm"
whileHover={{ scale: 1.1, y: -2 }}
whileTap={{ scale: 0.95 }}
aria-label="Shopping bag"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"
/>
</svg>
</motion.button>
</div>
</div>
</nav>
</motion.header>
{/* Mobile Menu Overlay - Only visible on mobile */}
<AnimatePresence>
{isMobileMenuOpen && (
<motion.div
className="mobile-menu fixed inset-0 z-50 bg-black/50 backdrop-blur-sm md:hidden"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
>
<motion.div
className="absolute top-[72px] left-0 right-0 bg-white/95 backdrop-blur-md border-t border-white/20 shadow-premium"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, delay: 0.1 }}
>
<div className="px-6 py-8 space-y-6">
{/* Mobile Navigation Links */}
<div className="space-y-4">
<motion.a
href="#about"
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
style={{
fontWeight: 300,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
onClick={() => setIsMobileMenuOpen(false)}
whileHover={{ x: 10 }}
>
About us
</motion.a>
<motion.a
href="#shop"
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
style={{
fontWeight: 300,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
onClick={() => setIsMobileMenuOpen(false)}
whileHover={{ x: 10 }}
>
Shop
</motion.a>
<motion.a
href="#categories"
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
style={{
fontWeight: 300,
fontFamily: "Renner",
fontSize: "18px",
lineHeight: "100%",
letterSpacing: "0%",
}}
onClick={() => setIsMobileMenuOpen(false)}
whileHover={{ x: 10 }}
>
Categories
</motion.a>
</div>
{/* Mobile Action Buttons */}
<div className="flex space-x-4 pt-4">
<motion.button
className="flex-1 p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm border border-gray-200"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
aria-label="Search"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</motion.button>
<motion.button
className="flex-1 p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm border border-gray-200"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
aria-label="Shopping bag"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"
/>
</svg>
</motion.button>
<motion.button
className="flex-1 p-3 text-gray-800 hover:text-[#8B4513] transition-all duration-300 relative min-h-[40px] flex items-center justify-center rounded-full hover:bg-white/20 backdrop-blur-sm border border-gray-200"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
aria-label="User account"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</motion.button>
</div>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</>
);
}