| import { useState, useEffect } from "react"; |
| import { Menu, X, Download, ShieldCheck } from "lucide-react"; |
| import { motion, AnimatePresence } from "motion/react"; |
| import { Link, useLocation } from "react-router-dom"; |
|
|
| interface NavbarProps { |
| downloadUrl: string; |
| } |
|
|
| export default function Navbar({ downloadUrl }: NavbarProps) { |
| const [isOpen, setIsOpen] = useState(false); |
| const [isScrolled, setIsScrolled] = useState(false); |
| const location = useLocation(); |
|
|
| const navItems = [ |
| { name: "Home", path: "/" }, |
| { name: "Features Specs", path: "/features" }, |
| { name: "FAQ Hub", path: "/faq" }, |
| { name: "Support Us", path: "/support" }, |
| { name: "Contact Specialist", path: "/contact" }, |
| ]; |
|
|
| useEffect(() => { |
| const handleScroll = () => { |
| setIsScrolled(window.scrollY > 20); |
| }; |
|
|
| window.addEventListener("scroll", handleScroll); |
| return () => window.removeEventListener("scroll", handleScroll); |
| }, []); |
|
|
| |
| useEffect(() => { |
| setIsOpen(false); |
| window.scrollTo(0, 0); |
| }, [location.pathname]); |
|
|
| const activePath = location.pathname; |
|
|
| return ( |
| <> |
| <nav |
| id="main-nav" |
| className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${ |
| isScrolled |
| ? "py-3 px-4 md:px-8 bg-white/80 backdrop-blur-md shadow-sm border-b border-slate-100" |
| : "py-5 px-4 md:px-8 bg-transparent" |
| }`} |
| > |
| <div className="max-w-7xl mx-auto flex items-center justify-between"> |
| {/* Logo */} |
| <Link |
| to="/" |
| className="flex items-center space-x-2 group focus:outline-none cursor-pointer" |
| id="nav-logo-btn" |
| > |
| <div className="w-10 h-10 rounded-xl bg-gradient-to-tr from-violet-600 to-indigo-600 flex items-center justify-center shadow-md shadow-violet-500/20 group-hover:scale-105 transition-transform duration-300"> |
| <ShieldCheck className="w-5 h-5 text-white" /> |
| </div> |
| <div className="text-left"> |
| <span className="block font-display font-medium text-lg text-slate-900 tracking-tight"> |
| Lumina Convert |
| </span> |
| <span className="block text-[10px] font-mono tracking-wider text-violet-600 -mt-1 font-semibold uppercase"> |
| All File Converter |
| </span> |
| </div> |
| </Link> |
| |
| {/* Desktop Nav Items */} |
| <div className="hidden md:flex items-center space-x-8"> |
| <div className="flex items-center space-x-6"> |
| {navItems.map((item) => ( |
| <Link |
| key={item.path} |
| to={item.path} |
| id={`nav-item-${item.name.toLowerCase().replace(/\s+/g, "-")}`} |
| className={`text-sm font-semibold tracking-wide transition-colors cursor-pointer relative py-1.5 focus:outline-none ${ |
| activePath === item.path |
| ? "text-violet-600 font-bold" |
| : "text-slate-600 hover:text-slate-900" |
| }`} |
| > |
| <span>{item.name}</span> |
| {activePath === item.path && ( |
| <motion.div |
| layoutId="activeIndicator" |
| className="absolute bottom-0 left-0 right-0 h-0.5 bg-violet-600 rounded-full" |
| transition={{ type: "spring", stiffness: 380, damping: 30 }} |
| /> |
| )} |
| </Link> |
| ))} |
| </div> |
| |
| {/* Premium CTA Button */} |
| <a |
| href={downloadUrl} |
| download |
| id="navbar-download-btn" |
| className="inline-flex items-center justify-center space-x-2 px-6 py-2.5 rounded-full bg-slate-900 text-white text-sm font-semibold shadow-md shadow-slate-900/10 hover:bg-violet-600 hover:shadow-violet-500/20 active:scale-95 transition-all duration-300 cursor-pointer" |
| > |
| <Download className="w-4 h-4" /> |
| <span>Download Free</span> |
| </a> |
| </div> |
| |
| {/* Mobile Menu Button */} |
| <div className="flex md:hidden items-center space-x-2"> |
| <a |
| href={downloadUrl} |
| download |
| id="navbar-download-mobile-btn" |
| className="p-2.5 rounded-full bg-slate-900 text-white shadow-sm hover:bg-violet-600 transition-colors cursor-pointer" |
| title="Download Converter" |
| > |
| <Download className="w-4 h-4" /> |
| </a> |
| <button |
| onClick={() => setIsOpen(!isOpen)} |
| id="mobile-menu-toggle-btn" |
| className="p-2 text-slate-700 hover:text-slate-900 focus:outline-none cursor-pointer" |
| aria-label="Toggle navigation menu" |
| > |
| {isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />} |
| </button> |
| </div> |
| </div> |
| </nav> |
| |
| {/* Mobile Drawer Overlay */} |
| <AnimatePresence> |
| {isOpen && ( |
| <> |
| {/* Backdrop */} |
| <motion.div |
| initial={{ opacity: 0 }} |
| animate={{ opacity: 1 }} |
| exit={{ opacity: 0 }} |
| onClick={() => setIsOpen(false)} |
| className="fixed inset-0 bg-slate-900/20 backdrop-blur-sm z-40 md:hidden" |
| /> |
| |
| {/* Sidebar drawer */} |
| <motion.div |
| initial={{ x: "100%" }} |
| animate={{ x: 0 }} |
| exit={{ x: "100%" }} |
| transition={{ type: "spring", damping: 25, stiffness: 200 }} |
| className="fixed right-0 top-0 bottom-0 w-72 bg-white z-50 p-6 shadow-2xl flex flex-col justify-between border-l border-slate-100 md:hidden" |
| > |
| <div> |
| <div className="flex items-center justify-between mb-8"> |
| <div className="flex items-center space-x-2"> |
| <div className="w-8 h-8 rounded-lg bg-gradient-to-tr from-violet-600 to-indigo-600 flex items-center justify-center shadow-md"> |
| <ShieldCheck className="w-4 h-4 text-white" /> |
| </div> |
| <span className="font-display font-semibold text-slate-900">Lumina Convert</span> |
| </div> |
| <button |
| onClick={() => setIsOpen(false)} |
| id="mobile-drawer-close-btn" |
| className="p-1 rounded-full hover:bg-slate-100 text-slate-500 cursor-pointer" |
| > |
| <X className="w-5 h-5" /> |
| </button> |
| </div> |
| |
| <div className="flex flex-col space-y-2"> |
| {navItems.map((item) => ( |
| <Link |
| key={item.path} |
| to={item.path} |
| id={`mobile-nav-item-${item.name.toLowerCase().replace(/\s+/g, "-")}`} |
| className={`text-left py-3 px-4 rounded-xl text-sm font-semibold tracking-wide transition-colors cursor-pointer flex justify-between items-center ${ |
| activePath === item.path |
| ? "bg-violet-50 text-violet-600 font-bold" |
| : "text-slate-600 hover:bg-slate-50" |
| }`} |
| > |
| <span>{item.name}</span> |
| {activePath === item.path && ( |
| <div className="w-1.5 h-1.5 rounded-full bg-violet-600" /> |
| )} |
| </Link> |
| ))} |
| </div> |
| </div> |
| |
| <div className="space-y-4"> |
| <div className="p-4 rounded-2xl bg-slate-50 border border-slate-100"> |
| <h4 className="text-xs font-mono font-bold uppercase tracking-wider text-slate-500 mb-1"> |
| v1.4.2 Standalone |
| </h4> |
| <p className="text-[11px] text-slate-600 mb-3">Offline GPU acceleration included.</p> |
| <a |
| href={downloadUrl} |
| download |
| id="mobile-drawer-download-cta" |
| className="w-full inline-flex items-center justify-center space-x-2 py-3 rounded-xl bg-violet-600 text-white font-medium text-xs shadow-md hover:bg-violet-700 active:scale-95 transition-all cursor-pointer" |
| > |
| <Download className="w-4 h-4" /> |
| <span>Download Installer</span> |
| </a> |
| </div> |
| </div> |
| </motion.div> |
| </> |
| )} |
| </AnimatePresence> |
| </> |
| ); |
| } |
|
|