完善页头样式
This commit is contained in:
@@ -1,59 +1,96 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import {ReactNode, useEffect, useState} from 'react'
|
import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import Wrap from '@/components/wrap'
|
import Wrap from '@/components/wrap'
|
||||||
|
|
||||||
export type HeaderProps = {}
|
export type HeaderProps = {}
|
||||||
|
|
||||||
export default function Header(props: 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(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('scroll', handleScroll)
|
window.removeEventListener('scroll', handleScroll)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [handleScroll])
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// 菜单状态
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
const [menu, setMenu] = useState<string>('')
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// 覆盖状态
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
const [overlay, setOverlay] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOverlay(scroll || menu !== '')
|
||||||
|
}, [menu, scroll])
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// 渲染组件
|
||||||
|
// ======================
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={[
|
className={[
|
||||||
`w-full h-24 max-md:h-16 overflow-hidden fixed top-0 shadow-lg`,
|
`fixed top-0 w-full`,
|
||||||
`transition-shadow duration-200 ${isScrolled ? 'bg-[rgba(255,255,255,0.9)] backdrop-blur-sm' : 'bg-transparent shadow-transparent'}`,
|
`transition-all duration-200 ${overlay ? `bg-[#fffe] shadow-lg backdrop-blur-sm` : 'bg-transparent shadow-transparent'}`,
|
||||||
].join(' ')}>
|
].join(' ')}>
|
||||||
<Wrap className="flex h-full items-center justify-between">
|
<Wrap className=" h-20 max-md:h-16 flex justify-between">
|
||||||
|
<div className="flex justify-between gap-8">
|
||||||
<div className="flex items-center justify-between gap-8">
|
|
||||||
{/* logo */}
|
{/* 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`}/>
|
<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>
|
</Link>
|
||||||
|
|
||||||
{/* 菜单 */}
|
{/* 菜单 */}
|
||||||
<nav className={`flex items-center max-lg:hidden`}>
|
<nav>
|
||||||
<ul className="flex items-center text-xl">
|
<ul className="h-full flex items-center text-xl max-lg:hidden">
|
||||||
<NavItemTop>
|
<NavItemTop>
|
||||||
<Link href={`/`}>首页</Link>
|
<Link href={`/`}>首页</Link>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
<NavItemTop>
|
|
||||||
<button>产品订购</button>
|
<NavItemTop
|
||||||
|
onEnter={() => setMenu('product')}
|
||||||
|
onLeave={() => setMenu('')}
|
||||||
|
>
|
||||||
|
<button className={`cursor-pointer`}>产品订购</button>
|
||||||
<SvgDown/>
|
<SvgDown/>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
<NavItemTop>
|
|
||||||
<button>业务场景</button>
|
<NavItemTop
|
||||||
|
onEnter={() => setMenu('solution')}
|
||||||
|
onLeave={() => setMenu('')}
|
||||||
|
>
|
||||||
|
<button className={`cursor-pointer`}>业务场景</button>
|
||||||
<SvgDown/>
|
<SvgDown/>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
<NavItemTop>
|
|
||||||
<button>帮助中心</button>
|
<NavItemTop
|
||||||
|
onEnter={() => setMenu('help')}
|
||||||
|
onLeave={() => setMenu('')}
|
||||||
|
>
|
||||||
|
<button className={`cursor-pointer`}>帮助中心</button>
|
||||||
<SvgDown/>
|
<SvgDown/>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
|
|
||||||
<NavItemTop>
|
<NavItemTop>
|
||||||
<Link href={`#`}>企业服务</Link>
|
<Link href={`#`}>企业服务</Link>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
|
|
||||||
<NavItemTop>
|
<NavItemTop>
|
||||||
<Link href={`#`}>推广返利</Link>
|
<Link href={`#`}>推广返利</Link>
|
||||||
</NavItemTop>
|
</NavItemTop>
|
||||||
@@ -74,17 +111,34 @@ export default function Header(props: HeaderProps) {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Wrap>
|
</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>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NavItemTopProps = {
|
function NavItemTop(props: {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
onEnter?: () => void
|
||||||
|
onLeave?: () => void
|
||||||
function NavItemTop(props: NavItemTopProps) {
|
}) {
|
||||||
return (
|
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}
|
{props.children}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
@@ -99,3 +153,41 @@ function SvgDown() {
|
|||||||
</svg>
|
</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