完善页头样式

This commit is contained in:
2025-03-12 15:13:37 +08:00
parent 8ea085463e
commit e592137370

View File

@@ -1,59 +1,96 @@
'use client'
import {ReactNode, useEffect, useState} from 'react'
import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
import Link from 'next/link'
import Wrap from '@/components/wrap'
export type HeaderProps = {}
export default function Header(props: HeaderProps) {
const [isScrolled, setIsScrolled] = useState(window.scrollY > 48)
const handleScroll = () => {
setIsScrolled(window.scrollY > 48)
}
// ======================
// 滚动条状态
// ======================
const [scroll, setScroll] = useState(window.scrollY > 48)
const handleScroll = useCallback(() => {
setScroll(window.scrollY > 48)
}, [])
useEffect(() => {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
}, [handleScroll])
// ======================
// 菜单状态
// ======================
const [menu, setMenu] = useState<string>('')
// ======================
// 覆盖状态
// ======================
const [overlay, setOverlay] = useState(false)
useEffect(() => {
setOverlay(scroll || menu !== '')
}, [menu, scroll])
// ======================
// 渲染组件
// ======================
return (
<header
className={[
`w-full h-24 max-md:h-16 overflow-hidden fixed top-0 shadow-lg`,
`transition-shadow duration-200 ${isScrolled ? 'bg-[rgba(255,255,255,0.9)] backdrop-blur-sm' : 'bg-transparent shadow-transparent'}`,
`fixed top-0 w-full`,
`transition-all duration-200 ${overlay ? `bg-[#fffe] shadow-lg backdrop-blur-sm` : 'bg-transparent shadow-transparent'}`,
].join(' ')}>
<Wrap className="flex h-full items-center justify-between">
<div className="flex items-center justify-between gap-8">
<Wrap className=" h-20 max-md:h-16 flex justify-between">
<div className="flex justify-between gap-8">
{/* logo */}
<Link href="/">
<Link href="/" className={`flex items-center`}>
<img src={`/logo.svg`} alt={`logo`} className={`w-16 max-md:w-12 h-16 max-md:h-12 rounded-full bg-gray-100`}/>
</Link>
{/* 菜单 */}
<nav className={`flex items-center max-lg:hidden`}>
<ul className="flex items-center text-xl">
<nav>
<ul className="h-full flex items-center text-xl max-lg:hidden">
<NavItemTop>
<Link href={`/`}></Link>
</NavItemTop>
<NavItemTop>
<button></button>
<NavItemTop
onEnter={() => setMenu('product')}
onLeave={() => setMenu('')}
>
<button className={`cursor-pointer`}></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<button></button>
<NavItemTop
onEnter={() => setMenu('solution')}
onLeave={() => setMenu('')}
>
<button className={`cursor-pointer`}></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<button></button>
<NavItemTop
onEnter={() => setMenu('help')}
onLeave={() => setMenu('')}
>
<button className={`cursor-pointer`}></button>
<SvgDown/>
</NavItemTop>
<NavItemTop>
<Link href={`#`}></Link>
</NavItemTop>
<NavItemTop>
<Link href={`#`}>广</Link>
</NavItemTop>
@@ -74,17 +111,34 @@ export default function Header(props: HeaderProps) {
</a>
</div>
</Wrap>
{/* 下拉菜单 */}
<div
className={[
`transition-[visibility,opacity,height] duration-200 ease-in-out`,
`${menu === ''
? 'delay-[200ms,0s,0s] invisible opacity-0 h-0 pointer-events-none'
: 'delay-[0s,0s,0s] visible opacity-100 h-80'
}`,
].join(' ')}>
</div>
{{
'product': <ProductMenu/>,
'solution': <SolutionMenu/>,
'help': <HelpMenu/>,
}[menu]}
Using a wrapper div to handle transitions
</header>
)
}
type NavItemTopProps = {
function NavItemTop(props: {
children: ReactNode
}
function NavItemTop(props: NavItemTopProps) {
onEnter?: () => void
onLeave?: () => void
}) {
return (
<li className={`px-4 h-10 flex items-center text-xl`}>
<li className={`h-10 px-4 flex items-center text-xl cursor-pointer`} onPointerEnter={props.onEnter} onPointerLeave={props.onLeave}>
{props.children}
</li>
)
@@ -99,3 +153,41 @@ function SvgDown() {
</svg>
)
}
function ProductMenu() {
const [type, setType] = useState<'domestic' | 'oversea'>('domestic')
return (
<div className={`flex`}>
<ul role={`tablist`}>
<li role={`tab`}>
<button onClick={() => setType('domestic')}>
</button>
</li>
<li role={`tab`}>
<button onClick={() => setType('oversea')}>
</button>
</li>
</ul>
<section role={`tabpanel`}>
{{
'domestic': <div></div>,
'oversea': <div></div>,
}[type]}
</section>
</div>
)
}
function SolutionMenu() {
return (
<div></div>
)
}
function HelpMenu() {
return (
<div></div>
)
}