Files
company-site/components/navbar.tsx
JanYork 6a68a96287 feat: 添加连锁门店系统首页及核心UI组件
新增首页布局、导航栏、页脚及多个核心UI组件(按钮、卡片、表格等)
添加图片资源、工具函数和样式配置
实现响应式设计和主题支持
包含行业解决方案展示区块
2026-03-18 10:50:42 +08:00

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>
)
}