diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 1350193..bf983b6 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,12 +1,35 @@ -import { NavLink, Link, useNavigate, useLocation } from "react-router-dom"; -import { useState, useContext } from "react"; +import { NavLink, Link } from "react-router-dom"; +import { useState, useContext, useRef, useEffect } from "react"; import { ThemeContext } from "../context/ThemeContext"; import { Moon, Sun, Menu, X } from "lucide-react"; +const navItems = [ + { to: "/", label: "Home" }, + { to: "/track", label: "Tracker" }, + { to: "/contributors", label: "Contributors" }, + { to: "/login", label: "Login" }, +]; + const Navbar: React.FC = () => { const [isOpen, setIsOpen] = useState(false); - const [user, setUser] = useState(() => readStoredUser()); - + const [pillStyle, setPillStyle] = useState<{ + left: number; + width: number; + opacity: number; + }>({ left: 0, width: 0, opacity: 0 }); + + const [scrolled,setScrolled]= useState(false); + useEffect( () => { + const handleScroll = () => { + setScrolled(window.scrollY>20); + }; + + handleScroll(); + window.addEventListener("scroll", handleScroll, { passive: true }); + return () => window.removeEventListener("scroll", handleScroll); + },[]); + + const navRef = useRef(null); const themeContext = useContext(ThemeContext); const navigate = useNavigate(); const location = useLocation(); @@ -16,55 +39,39 @@ const Navbar: React.FC = () => { const { toggleTheme, mode } = themeContext; const { isAuthenticated, isLoading, logout } = authContext; - const navLinkStyles = ({ isActive }: { isActive: boolean }) => - `px-4 py-2 rounded-xl text-sm lg:text-base font-semibold transition-all duration-300 ${ - isActive - ? "text-blue-600 bg-blue-100 dark:text-blue-400 dark:bg-blue-900/40 shadow-sm" - : "text-slate-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800" - }`; - - const featureLinkStyles = - "px-4 py-2 rounded-xl text-sm lg:text-base font-semibold transition-all duration-300 text-slate-700 dark:text-gray-300 hover:text-blue-500 cursor-pointer"; - const closeMenu = () => setIsOpen(false); - const handleLogout = () => { - if (typeof window !== "undefined") { - window.localStorage.removeItem(AUTH_STORAGE_KEY); - } - setUser(null); - closeMenu(); - }; - const handleLogout = async () => { - try { - await logout(); - navigate("/login", { replace: true }); - } catch { - // optionally surface a toast/message - } finally { - closeMenu(); - } + const handleMouseEnter = (e: React.MouseEvent) => { + const nav = navRef.current; + const item = e.currentTarget; + if (!nav) return; + const navRect = nav.getBoundingClientRect(); + const itemRect = item.getBoundingClientRect(); + setPillStyle({ + left: itemRect.left - navRect.left, + width: itemRect.width, + opacity: 1, + }); }; - // Smooth scroll to #features on homepage - const handleFeaturesClick = () => { - closeMenu(); - if (location.pathname === "/") { - const section = document.getElementById("features"); - if (section) { - section.scrollIntoView({ behavior: "smooth" }); - } - } else { - navigate("/#features"); - setTimeout(() => { - const section = document.getElementById("features"); - if (section) section.scrollIntoView({ behavior: "smooth" }); - }, 100); - } + const handleMouseLeave = () => { + setPillStyle((prev) => ({ ...prev, opacity: 0 })); }; + const navLinkClass = ({ isActive }: { isActive: boolean }) => + `relative z-10 px-4 py-2 rounded-xl text-sm lg:text-base font-semibold transition-colors duration-200 ${ + isActive + ? "text-blue-600 dark:text-blue-400" + : "text-slate-700 dark:text-gray-300" + }`; + return ( -