Spaces:
Running
Running
| import React, { useState } from 'react'; | |
| import { Link, useLocation } from 'react-router-dom'; | |
| const Navbar = () => { | |
| const [isMenuOpen, setIsMenuOpen] = useState(false); | |
| const location = useLocation(); | |
| const navLinks = [ | |
| { name: 'Home', path: '/' }, | |
| { name: 'Missions', path: '/missions' }, | |
| { name: 'Partnerships', path: '/partnerships' }, | |
| { name: 'Accountability', path: '/accountability' }, | |
| { name: 'Metrics', path: '/metrics' }, | |
| { name: 'Indigenous Voices', path: '/indigenous' }, | |
| { name: 'Deliberation', path: '/deliberation' }, | |
| ]; | |
| const toggleDarkMode = () => { | |
| if (document.documentElement.classList.contains('dark')) { | |
| document.documentElement.classList.remove('dark'); | |
| localStorage.theme = 'light'; | |
| } else { | |
| document.documentElement.classList.add('dark'); | |
| localStorage.theme = 'dark'; | |
| } | |
| }; | |
| return ( | |
| <nav className="bg-white/80 dark:bg-slate-800/80 backdrop-blur-lg shadow-lg border-b border-white/20"> | |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div className="flex justify-between h-20"> | |
| <div className="flex items-center"> | |
| <Link to="/" className="flex-shrink-0 flex items-center"> | |
| <span className="text-2xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent dark:from-indigo-400 dark:to-purple-400"> | |
| SDGLIV/GXS | |
| </span> | |
| </Link> | |
| </div> | |
| {/* Desktop menu */} | |
| <div className="hidden md:flex items-center space-x-1"> | |
| {navLinks.map((link) => ( | |
| <NavLink | |
| key={link.path} | |
| to={link.path} | |
| isActive={location.pathname === link.path} | |
| > | |
| {link.name} | |
| </NavLink> | |
| ))} | |
| {/* Dark mode toggle */} | |
| <button | |
| onClick={toggleDarkMode} | |
| className="ml-4 p-2 rounded-full text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-slate-700 focus:outline-none" | |
| aria-label="Toggle dark mode" | |
| > | |
| <svg | |
| className="w-6 h-6 hidden dark:block" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > | |
| <path | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| strokeWidth={2} | |
| d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" | |
| /> | |
| </svg> | |
| <svg | |
| className="w-6 h-6 dark:hidden" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > | |
| <path | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| strokeWidth={2} | |
| d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" | |
| /> | |
| </svg> | |
| </button> | |
| </div> | |
| {/* Mobile menu button */} | |
| <div className="md:hidden flex items-center"> | |
| <button | |
| onClick={toggleDarkMode} | |
| className="p-2 mr-2 rounded-full text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-slate-700 focus:outline-none" | |
| aria-label="Toggle dark mode" | |
| > | |
| <svg | |
| className="w-6 h-6 hidden dark:block" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > | |
| <path | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| strokeWidth={2} | |
| d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" | |
| /> | |
| </svg> | |
| <svg | |
| className="w-6 h-6 dark:hidden" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| xmlns="http://www.w3.org/2000/svg" | |
| > | |
| <path | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| strokeWidth={2} | |
| d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" | |
| /> | |
| </svg> | |
| </button> | |
| <button | |
| onClick={() => setIsMenuOpen(!isMenuOpen)} | |
| className="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-indigo-600 dark:text-gray-300 dark:hover:text-indigo-400 focus:outline-none" | |
| > | |
| <svg | |
| className={`${isMenuOpen ? 'hidden' : 'block'} h-8 w-8`} | |
| stroke="currentColor" | |
| fill="none" | |
| viewBox="0 0 24 24" | |
| > | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16" /> | |
| </svg> | |
| <svg | |
| className={`${isMenuOpen ? 'block' : 'hidden'} h-8 w-8`} | |
| stroke="currentColor" | |
| fill="none" | |
| viewBox="0 0 24 24" | |
| > | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Mobile menu */} | |
| <div className={`${isMenuOpen ? 'block' : 'hidden'} md:hidden`}> | |
| <div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white/90 dark:bg-slate-800/90 backdrop-blur-lg rounded-b-2xl border border-white/20 shadow-lg"> | |
| {navLinks.map((link) => ( | |
| <MobileNavLink | |
| key={link.path} | |
| to={link.path} | |
| isActive={location.pathname === link.path} | |
| onClick={() => setIsMenuOpen(false)} | |
| > | |
| {link.name} | |
| </MobileNavLink> | |
| ))} | |
| </div> | |
| </div> | |
| </nav> | |
| ); | |
| }; | |
| const NavLink = ({ to, children, isActive }) => ( | |
| <Link | |
| to={to} | |
| className={`px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 ${ | |
| isActive | |
| ? 'bg-gradient-to-r from-indigo-500 to-purple-500 text-white shadow-md' | |
| : 'text-gray-700 hover:bg-indigo-50 hover:text-indigo-600 dark:text-gray-300 dark:hover:bg-slate-700 dark:hover:text-indigo-400' | |
| }`} | |
| > | |
| {children} | |
| </Link> | |
| ); | |
| const MobileNavLink = ({ to, children, isActive, onClick }) => ( | |
| <Link | |
| to={to} | |
| onClick={onClick} | |
| className={`block px-4 py-3 rounded-lg text-base font-medium transition-all duration-200 ${ | |
| isActive | |
| ? 'bg-gradient-to-r from-indigo-500 to-purple-500 text-white shadow-md' | |
| : 'text-gray-700 hover:bg-indigo-50 hover:text-indigo-600 dark:text-gray-300 dark:hover:bg-slate-700 dark:hover:text-indigo-400' | |
| }`} | |
| > | |
| {children} | |
| </Link> | |
| ); | |
| export default Navbar; |