Spaces:
Running
Running
| import React, { useState, useEffect } from 'react'; | |
| import { Menu, X } from 'lucide-react'; | |
| import { NAV_LINKS } from '../constants'; | |
| import Button from './ui/Button'; | |
| interface NavbarProps { | |
| onStart?: () => void; | |
| onLogin?: () => void; | |
| user?: any; | |
| } | |
| const Navbar: React.FC<NavbarProps> = ({ onStart, onLogin, user }) => { | |
| const [isScrolled, setIsScrolled] = useState(false); | |
| const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); | |
| useEffect(() => { | |
| const handleScroll = () => { | |
| setIsScrolled(window.scrollY > 20); | |
| }; | |
| window.addEventListener('scroll', handleScroll); | |
| return () => window.removeEventListener('scroll', handleScroll); | |
| }, []); | |
| return ( | |
| <nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${isScrolled ? 'bg-black/80 backdrop-blur-md py-3 border-b border-gray-800' : 'bg-transparent py-5'}`}> | |
| <div className="max-w-7xl mx-auto px-6 flex items-center justify-between"> | |
| <div className="flex items-center gap-2 cursor-pointer" onClick={() => window.scrollTo(0,0)}> | |
| <div className="w-8 h-8 flex items-center justify-center font-bold text-xl text-white"> | |
| {/* Stylized Logo Mockup */} | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full"> | |
| <path d="M12 2L2 22h20L12 2z" className="text-gray-400" /> | |
| <path d="M12 6L6 20h12L12 6z" className="text-white fill-white" /> | |
| </svg> | |
| </div> | |
| <span className="font-semibold text-lg tracking-tight">SyncUsers</span> | |
| </div> | |
| {/* Desktop Nav */} | |
| <div className="hidden md:flex items-center gap-8"> | |
| {NAV_LINKS.map((link) => ( | |
| <a | |
| key={link.label} | |
| href={link.href} | |
| className="text-sm font-medium text-gray-300 hover:text-white transition-colors" | |
| > | |
| {link.label} | |
| </a> | |
| ))} | |
| </div> | |
| <div className="hidden md:flex items-center gap-4"> | |
| {user ? ( | |
| <div className="flex items-center gap-3 bg-gray-900 border border-gray-800 rounded-full px-4 py-1.5"> | |
| {user.avatarUrl && <img src={user.avatarUrl} alt={user.preferred_username} className="w-6 h-6 rounded-full" />} | |
| <span className="text-sm font-medium text-gray-300">{user.preferred_username}</span> | |
| </div> | |
| ) : ( | |
| <Button variant="outline" size="sm" onClick={onLogin}>Sign in with HF</Button> | |
| )} | |
| <Button variant="primary" size="sm" onClick={onStart}>Start Building</Button> | |
| </div> | |
| {/* Mobile Toggle */} | |
| <button | |
| className="md:hidden text-gray-300 hover:text-white" | |
| onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} | |
| > | |
| {isMobileMenuOpen ? <X /> : <Menu />} | |
| </button> | |
| </div> | |
| {/* Mobile Menu */} | |
| {isMobileMenuOpen && ( | |
| <div className="md:hidden bg-black border-t border-gray-800 p-6 absolute top-full left-0 right-0"> | |
| <div className="flex flex-col gap-4"> | |
| {NAV_LINKS.map((link) => ( | |
| <a | |
| key={link.label} | |
| href={link.href} | |
| className="text-lg font-medium text-gray-300 hover:text-white" | |
| onClick={() => setIsMobileMenuOpen(false)} | |
| > | |
| {link.label} | |
| </a> | |
| ))} | |
| <div className="pt-4 flex flex-col gap-3"> | |
| {user ? ( | |
| <div className="flex items-center gap-3 bg-gray-900 border border-gray-800 rounded-lg px-4 py-3"> | |
| {user.avatarUrl && <img src={user.avatarUrl} alt={user.preferred_username} className="w-8 h-8 rounded-full" />} | |
| <span className="font-medium text-gray-300">{user.preferred_username}</span> | |
| </div> | |
| ) : ( | |
| <Button variant="outline" className="w-full" onClick={() => { setIsMobileMenuOpen(false); if(onLogin) onLogin(); }}>Sign in with HF</Button> | |
| )} | |
| <Button variant="primary" className="w-full" onClick={() => { setIsMobileMenuOpen(false); if(onStart) onStart(); }}>Start Building</Button> | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| </nav> | |
| ); | |
| }; | |
| export default Navbar; |