diff --git a/src/App.tsx b/src/App.tsx index 3187552..908d57f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,7 @@ import { Toaster } from "@/components/ui/toaster"; import { Toaster as Sonner } from "@/components/ui/sonner"; import { TooltipProvider } from "@/components/ui/tooltip"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; import Index from "./pages/Index"; import NotFound from "./pages/NotFound"; import ProjectPage from "./pages/ProjectPage"; @@ -13,6 +13,21 @@ const queryClient = new QueryClient(); const IndexWrapper = () => ; +const router = createBrowserRouter([ + { + path: "/", + element: , + }, + { + path: "/project/:projectId", + element: , + }, + { + path: "*", + element: , + }, +]); + const App = () => ( @@ -20,14 +35,7 @@ const App = () => ( - - - } /> - } /> - {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} - } /> - - + diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 83f5916..1605689 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,26 +1,53 @@ -import { Moon, Sun } from "lucide-react"; +import { Moon, Sun, Menu, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useTheme } from "@/contexts/ThemeContext"; import { useLanguage } from "@/contexts/LanguageContext"; -import { motion } from "framer-motion"; +import { motion, AnimatePresence } from "framer-motion"; import { useLocation, useNavigate } from "react-router-dom"; +import { useState, useEffect, useRef } from "react"; export const Header = () => { const { theme, toggleTheme } = useTheme(); const { language, setLanguage, t } = useLanguage(); const location = useLocation(); const navigate = useNavigate(); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const mobileMenuRef = useRef(null); // Check if we're on a project page const isProjectPage = location.pathname.startsWith('/project/'); + // Close mobile menu when clicking outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (mobileMenuRef.current && !mobileMenuRef.current.contains(event.target as Node)) { + setMobileMenuOpen(false); + } + }; + + if (mobileMenuOpen) { + document.addEventListener('mousedown', handleClickOutside); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [mobileMenuOpen]); + const handleNavigation = (section: string) => { + // Close mobile menu immediately + setMobileMenuOpen(false); + + // Then scroll to section (happens independently) if (isProjectPage) { // If on project page, navigate to home with section anchor navigate(`/#${section}`); } else { // If on home page, scroll to section - scrollToSection(section); + // Use setTimeout to ensure scroll happens after menu animation starts + setTimeout(() => { + scrollToSection(section); + }, 100); } }; @@ -50,6 +77,7 @@ export const Header = () => { initial={{ y: -100 }} animate={{ y: 0 }} className="fixed top-0 left-0 right-0 z-50 border-b border-border/40 bg-background/80 backdrop-blur-lg" + ref={mobileMenuRef} >
{ AP + {/* Desktop Navigation */}
+ + {/* Mobile Navigation */} + + {mobileMenuOpen && ( + +
+ {["home", "projects", "skills", "contact"].map((item, i) => ( + handleNavigation(item)} + className="text-left text-base font-medium text-muted-foreground hover:text-foreground transition-colors py-2" + > + {t(`nav.${item}`)} + + ))} +
+
+ )} +
); }; diff --git a/src/components/ParticlesBackground.tsx b/src/components/ParticlesBackground.tsx index 2b6b6ab..4056407 100644 --- a/src/components/ParticlesBackground.tsx +++ b/src/components/ParticlesBackground.tsx @@ -16,7 +16,7 @@ export const ParticlesBackground = () => { }, []); const particlesLoaded = async (container) => { - console.log(container); + // console.log(container); }; const options = useMemo(