完善页头样式
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user