2025-12-18 18:32:35 +08:00

163 lines
5.9 KiB
TypeScript

'use client';
import React, { useState, useEffect, useTransition } from 'react';
import { Menu, X, Globe } from 'lucide-react';
import { useTranslations, useLocale } from 'next-intl';
import { usePathname, useRouter } from '@/i18n/routing';
const Navbar: React.FC = () => {
const t = useTranslations('Navbar');
const locale = useLocale();
const router = useRouter();
const pathname = usePathname();
const [isPending, startTransition] = useTransition();
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isLangMenuOpen, setIsLangMenuOpen] = useState(false);
const navItems = [
{ label: t('home'), href: '#hero' },
{ label: t('about'), href: '#about' },
{ label: t('services'), href: '#services' },
{ label: t('contact'), href: '#contact' },
];
const onSelectChange = (nextLocale: string) => {
startTransition(() => {
router.replace(pathname, {locale: nextLocale});
});
setIsLangMenuOpen(false);
};
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 768) {
setIsMobileMenuOpen(false);
}
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<nav
className={`fixed top-0 left-0 w-full z-50 transition-all duration-300 ${
isScrolled || isMobileMenuOpen
? 'bg-feie-cream/95 backdrop-blur-md shadow-sm py-4'
: 'bg-transparent py-6'
}`}
>
<div className="container mx-auto px-6 flex justify-between items-center">
<a href="#" className="flex items-center gap-2 group">
<div className={`w-8 h-8 rounded-sm border-2 flex items-center justify-center transition-colors ${isScrolled || isMobileMenuOpen ? 'border-feie-dark text-feie-dark' : 'border-feie-white text-feie-white'}`}>
<span className="font-serif font-bold text-lg">F</span>
</div>
<span className={`font-serif text-xl font-bold tracking-wide transition-colors ${isScrolled || isMobileMenuOpen ? 'text-feie-dark' : 'text-feie-white'}`}>
FEIE TECH
</span>
</a>
{/* Desktop Menu */}
<div className="hidden md:flex items-center space-x-8">
{navItems.map((item) => (
<a
key={item.label}
href={item.href}
className={`font-serif text-sm tracking-widest uppercase hover:text-feie-gold transition-colors duration-300 ${
isScrolled ? 'text-feie-dark' : 'text-feie-white/90'
}`}
>
{item.label}
</a>
))}
{/* Language Switcher */}
<div className="relative">
<button
onClick={() => setIsLangMenuOpen(!isLangMenuOpen)}
className={`flex items-center gap-1 font-serif text-sm tracking-widest uppercase hover:text-feie-gold transition-colors duration-300 ${
isScrolled ? 'text-feie-dark' : 'text-feie-white/90'
}`}
>
<Globe size={16} />
<span>{locale.toUpperCase()}</span>
</button>
{isLangMenuOpen && (
<div className="absolute top-full right-0 mt-2 w-24 bg-white rounded-md shadow-lg py-1 z-50">
{['zh', 'en', 'ja'].map((l) => (
<button
key={l}
onClick={() => onSelectChange(l)}
className={`block w-full text-left px-4 py-2 text-sm hover:bg-gray-100 ${locale === l ? 'text-feie-gold font-bold' : 'text-gray-700'}`}
>
{l === 'zh' ? '中文' : l === 'en' ? 'English' : '日本語'}
</button>
))}
</div>
)}
</div>
</div>
{/* Mobile Toggle */}
<div className="md:hidden flex items-center gap-4">
{/* Mobile Language Switcher */}
<button
onClick={() => {
const nextLocale = locale === 'zh' ? 'en' : locale === 'en' ? 'ja' : 'zh';
onSelectChange(nextLocale);
}}
className={`flex items-center gap-1 font-serif text-sm tracking-widest uppercase ${
isScrolled || isMobileMenuOpen ? 'text-feie-dark' : 'text-feie-white'
}`}
>
{locale.toUpperCase()}
</button>
<button
className="focus:outline-none"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? (
<X className={isScrolled || isMobileMenuOpen ? 'text-feie-dark' : 'text-feie-white'} />
) : (
<Menu className={isScrolled || isMobileMenuOpen ? 'text-feie-dark' : 'text-feie-white'} />
)}
</button>
</div>
</div>
{/* Mobile Menu */}
<div
className={`md:hidden absolute top-full left-0 w-full bg-feie-cream/95 backdrop-blur-md border-t border-gray-200 shadow-lg flex flex-col items-center transition-all duration-300 ease-in-out overflow-hidden ${
isMobileMenuOpen ? 'max-h-96 opacity-100 py-6' : 'max-h-0 opacity-0 py-0'
}`}
>
<div className="flex flex-col items-center space-y-6 w-full">
{navItems.map((item) => (
<a
key={item.label}
href={item.href}
className="font-serif text-lg text-feie-dark hover:text-feie-gold transition-colors"
onClick={() => setIsMobileMenuOpen(false)}
>
{item.label}
</a>
))}
</div>
</div>
</nav>
);
};
export default Navbar;