feat: add copyright start years chore: update dependencies
This commit is contained in:
+117
-15
@@ -1,23 +1,125 @@
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useState, useCallback } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
// 导航链接配置
|
||||
const NAV_LINKS = [{ path: "/", label: "首页" }];
|
||||
|
||||
export default function Header() {
|
||||
const pathname = usePathname();
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
const toggleMenu = useCallback(() => {
|
||||
setIsMenuOpen((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
const closeMenu = useCallback(() => {
|
||||
setIsMenuOpen(false);
|
||||
}, []);
|
||||
|
||||
// 导航链接组件
|
||||
const NavLink = ({ href, children, className, onClick }: { href: string; children: React.ReactNode; className?: string; onClick?: () => void }) => (
|
||||
<Link href={href} className={pathname === href ? "no-underline" : ""} onClick={onClick}>
|
||||
<motion.div className={className} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} initial={false}>
|
||||
{children}
|
||||
</motion.div>
|
||||
</Link>
|
||||
);
|
||||
|
||||
// 按钮组件
|
||||
const NavButton = ({ onClick, children, className }: { onClick: () => void; children: React.ReactNode; className?: string }) => (
|
||||
<button onClick={onClick} className={className}>
|
||||
<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} initial={false}>
|
||||
{children}
|
||||
</motion.div>
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<header className="home-header px-4 w-full bg-white dark:bg-gray-950 shadow-sm flex sm:px-8">
|
||||
<nav className="container mx-auto flex justify-between items-center">
|
||||
<div className="flex items-center">
|
||||
<Link href="/">
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-gray-100">智能计算实验室</h1>
|
||||
</Link>
|
||||
<>
|
||||
<motion.header className="fixed top-0 left-0 right-0 bg-white/80 dark:bg-gray-950/80 py-3 px-5 z-40 backdrop-blur-sm shadow-sm">
|
||||
<nav className="container max-w-7xl mx-auto flex justify-between items-center">
|
||||
<div className="flex items-center">
|
||||
<Link href="/">
|
||||
<motion.h1 className="text-xl font-bold text-gray-900 dark:text-gray-100" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }}>
|
||||
智能计算实验室
|
||||
</motion.h1>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* 桌面端导航 */}
|
||||
<div className="hidden md:flex space-x-6">
|
||||
{NAV_LINKS.map((link) => (
|
||||
<NavLink
|
||||
key={link.path}
|
||||
href={link.path}
|
||||
className={`text-sm font-medium text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 ${
|
||||
pathname === link.path ? "border-b border-gray-600 dark:border-gray-400 hover:border-blue-600 dark:hover:border-blue-400" : "border-b border-transparent"
|
||||
}`}
|
||||
>
|
||||
{link.label}
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 移动端菜单按钮 */}
|
||||
<NavButton className="flex items-center md:hidden focus:outline-none" onClick={toggleMenu}>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="打开导航菜单" className="text-gray-900 dark:text-gray-100">
|
||||
<path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</NavButton>
|
||||
</nav>
|
||||
</motion.header>
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<div
|
||||
className={`md:hidden fixed inset-0 bg-black bg-opacity-50 z-40 transition-opacity duration-300 ${isMenuOpen ? "opacity-25" : "opacity-0 pointer-events-none"}`}
|
||||
onClick={closeMenu}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
{/* 移动端侧边菜单 */}
|
||||
<motion.div
|
||||
className="md:hidden fixed top-0 right-0 h-full w-64 bg-white dark:bg-gray-900 shadow-lg z-50"
|
||||
initial={{ x: "100%" }}
|
||||
animate={{ x: isMenuOpen ? 0 : "100%" }}
|
||||
transition={{
|
||||
type: "tween",
|
||||
ease: [0.05, 1, 0.5, 1],
|
||||
duration: 0.3,
|
||||
}}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="导航菜单"
|
||||
>
|
||||
<div className="flex justify-between items-center p-3 border-b border-gray-200 dark:border-gray-800">
|
||||
<h2 className="text-lg font-bold text-gray-900 dark:text-gray-100">智能计算实验室</h2>
|
||||
<NavButton onClick={closeMenu} className="focus:outline-none">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="关闭导航菜单" className="text-gray-900 dark:text-gray-100">
|
||||
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</NavButton>
|
||||
</div>
|
||||
<div className="flex space-x-4">
|
||||
<Link className="nav-link py-3 px-2 text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 transition-colors" href="/">
|
||||
首页
|
||||
</Link>
|
||||
{/* <Link className="nav-link py-3 px-2 text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 transition-colors" href="/">
|
||||
联系
|
||||
</Link> */}
|
||||
<div className="px-5 py-4">
|
||||
{NAV_LINKS.map((link) => (
|
||||
<NavLink
|
||||
key={link.path}
|
||||
href={link.path}
|
||||
className={`block py-3 text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400 ${
|
||||
pathname === link.path ? "border-l-2 border-blue-600 dark:border-blue-400 pl-3 font-medium" : "pl-3"
|
||||
}`}
|
||||
onClick={closeMenu}
|
||||
>
|
||||
{link.label}
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</motion.div>
|
||||
|
||||
{/* 避免被导航栏遮挡 */}
|
||||
<div className="h-16"></div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user