151 lines
5.5 KiB
TypeScript
151 lines
5.5 KiB
TypeScript
"use client"
|
|
|
|
import { useState, useEffect } from "react"
|
|
import Link from "next/link"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
|
import { Menu, X } from "lucide-react"
|
|
import { cn } from "@/lib/utils"
|
|
import siteData from "@/data/site.json"
|
|
|
|
export function Navbar() {
|
|
const [scrolled, setScrolled] = useState(false)
|
|
const [open, setOpen] = useState(false)
|
|
const { company, nav } = siteData
|
|
|
|
useEffect(() => {
|
|
const onScroll = () => setScrolled(window.scrollY > 40)
|
|
window.addEventListener("scroll", onScroll, { passive: true })
|
|
return () => window.removeEventListener("scroll", onScroll)
|
|
}, [])
|
|
|
|
return (
|
|
<header
|
|
className={cn(
|
|
"fixed top-0 left-0 right-0 z-50 transition-all duration-500",
|
|
scrolled
|
|
? "bg-white/95 backdrop-blur-md shadow-sm border-b border-border"
|
|
: "bg-transparent"
|
|
)}
|
|
>
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex items-center justify-between h-16 lg:h-20">
|
|
|
|
{/* Logo */}
|
|
<Link href="#home" className="flex flex-col leading-none group shrink-0">
|
|
<div className="flex flex-col gap-0.5">
|
|
<span className={cn(
|
|
"font-bold text-base tracking-tight transition-colors duration-300",
|
|
scrolled ? "text-foreground" : "text-white"
|
|
)}>
|
|
{company.name}
|
|
</span>
|
|
<span className={cn(
|
|
"text-[10px] tracking-widest transition-colors duration-300",
|
|
scrolled ? "text-muted-foreground" : "text-white/60"
|
|
)}>
|
|
{company.nameEn.toUpperCase()}
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
|
|
{/* Desktop Nav */}
|
|
<nav className="hidden lg:flex items-center gap-1" aria-label="主导航">
|
|
{nav.links.map((link) => (
|
|
<Link
|
|
key={link.label}
|
|
href={link.href}
|
|
className={cn(
|
|
"px-4 py-2 rounded-md text-sm font-medium transition-colors duration-200",
|
|
scrolled
|
|
? "text-muted-foreground hover:text-foreground hover:bg-muted"
|
|
: "text-white/80 hover:text-white hover:bg-white/10"
|
|
)}
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
|
|
{/* CTA */}
|
|
<div className="hidden lg:flex items-center gap-3">
|
|
<Button
|
|
asChild
|
|
size="sm"
|
|
className={cn(
|
|
"px-5 h-9 text-sm font-semibold shadow-sm transition-all duration-300",
|
|
scrolled
|
|
? "bg-primary hover:bg-primary-dark text-white"
|
|
: "bg-white text-primary hover:bg-white/90"
|
|
)}
|
|
>
|
|
<Link href="#contact">{nav.cta}</Link>
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Mobile Menu */}
|
|
<div className="lg:hidden">
|
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
<SheetTrigger asChild>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className={cn(
|
|
"transition-colors",
|
|
scrolled ? "text-foreground" : "text-white hover:bg-white/10"
|
|
)}
|
|
aria-label="打开菜单"
|
|
>
|
|
<Menu className="w-5 h-5" />
|
|
</Button>
|
|
</SheetTrigger>
|
|
<SheetContent side="right" className="w-72 p-0">
|
|
<div className="flex flex-col h-full">
|
|
<div className="flex items-center justify-between p-5 border-b border-border">
|
|
<div className="flex flex-col leading-none gap-1">
|
|
<span className="font-bold text-base text-foreground">{company.name}</span>
|
|
<span className="text-[10px] tracking-widest text-muted-foreground">
|
|
{company.nameEn.toUpperCase()}
|
|
</span>
|
|
</div>
|
|
<button
|
|
onClick={() => setOpen(false)}
|
|
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
aria-label="关闭菜单"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
<nav className="flex flex-col p-4 gap-1 flex-1" aria-label="移动端导航">
|
|
{nav.links.map((link) => (
|
|
<Link
|
|
key={link.label}
|
|
href={link.href}
|
|
onClick={() => setOpen(false)}
|
|
className="px-4 py-3 rounded-md text-sm font-medium text-foreground hover:bg-muted transition-colors"
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
<div className="p-4 border-t border-border">
|
|
<Button
|
|
asChild
|
|
className="w-full bg-primary hover:bg-primary-dark text-white"
|
|
>
|
|
<Link href="#contact" onClick={() => setOpen(false)}>
|
|
{nav.cta}
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</SheetContent>
|
|
</Sheet>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|