Files
CityCards-Website/src/components/SimpleNavbar.tsx
priyanshuvish 97969c079b new src added
2025-10-09 19:03:24 +05:30

177 lines
6.0 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Menu, X, ChevronDown, Globe } from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { Button } from './ui/button';
import { ImageWithFallback } from './figma/ImageWithFallback';
import logoImage from 'figma:asset/e96a0ba8c1e8ee053e3eb462a3b4552a8657e7b6.png';
interface SimpleNavbarProps {
onHomeClick?: () => void;
onMelbourneClick?: () => void;
onPassesClick?: () => void;
onSignInClick?: () => void;
onAttractionsClick?: () => void;
currentPage?: string;
}
export function Navbar({
onHomeClick,
onMelbourneClick,
onPassesClick,
onSignInClick,
onAttractionsClick,
currentPage = 'home'
}: SimpleNavbarProps) {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
// Handle scroll effect
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 0);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const navItems = [
{ label: 'Home', action: onHomeClick, active: currentPage === 'home' },
{ label: 'Melbourne', action: onMelbourneClick, active: currentPage === 'melbourne' },
{ label: 'Attractions', action: onAttractionsClick, active: currentPage === 'attractions' },
{ label: 'Passes', action: onPassesClick, active: currentPage === 'passes' }
];
return (
<motion.nav
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
isScrolled
? 'bg-white/95 backdrop-blur-md shadow-sm border-b border-gray-100'
: 'bg-transparent'
}`}
initial={{ y: -100 }}
animate={{ y: 0 }}
transition={{ duration: 0.5 }}
>
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
{/* Logo */}
<motion.div
className="flex items-center cursor-pointer"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={onHomeClick}
>
<ImageWithFallback
src={logoImage}
alt="CityCards Logo"
className="h-8 w-auto"
/>
</motion.div>
{/* Desktop Navigation */}
<div className="hidden md:flex items-center space-x-8">
{navItems.map((item) => (
<motion.button
key={item.label}
onClick={item.action}
className={`font-poppins relative px-4 py-2 font-medium transition-all duration-200 ${
item.active
? 'text-primary'
: 'text-gray-700 hover:text-gray-900'
}`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{item.label}
{item.active && (
<motion.div
className="absolute bottom-0 left-0 right-0 h-0.5 bg-gradient-to-r from-primary to-secondary rounded-full"
layoutId="activeTab"
/>
)}
</motion.button>
))}
</div>
{/* Right Section */}
<div className="hidden md:flex items-center space-x-4">
<div className="font-poppins flex items-center space-x-2 text-gray-700 hover:text-gray-900 px-3 py-2 font-medium transition-colors duration-200 cursor-pointer rounded-lg hover:bg-gray-50">
<Globe className="w-4 h-4" />
<span>ENG</span>
<ChevronDown className="w-3 h-3" />
</div>
<Button
onClick={onSignInClick}
variant="outline"
className="font-poppins font-medium border-primary text-primary hover:bg-primary hover:text-white"
>
Sign In
</Button>
</div>
{/* Mobile Menu Button */}
<div className="md:hidden">
<Button
variant="ghost"
size="sm"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? (
<X className="h-5 w-5" />
) : (
<Menu className="h-5 w-5" />
)}
</Button>
</div>
</div>
{/* Mobile Menu */}
<AnimatePresence>
{isMobileMenuOpen && (
<motion.div
className="md:hidden"
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2 }}
>
<div className="px-2 pt-2 pb-3 space-y-1 bg-white border-t border-gray-100">
{navItems.map((item) => (
<motion.button
key={item.label}
onClick={() => {
item.action?.();
setIsMobileMenuOpen(false);
}}
className={`block w-full text-left px-3 py-2 rounded-md font-medium transition-colors duration-200 ${
item.active
? 'text-primary bg-primary/10'
: 'text-gray-700 hover:text-gray-900 hover:bg-gray-50'
}`}
whileHover={{ x: 4 }}
>
{item.label}
</motion.button>
))}
<div className="pt-4 pb-2 border-t border-gray-100">
<Button
onClick={() => {
onSignInClick?.();
setIsMobileMenuOpen(false);
}}
className="w-full"
>
Sign In
</Button>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</motion.nav>
);
}