refactor: simplify header component and improve hero section layouts
This commit is contained in:
@@ -1,123 +1,61 @@
|
||||
'use client'
|
||||
|
||||
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import clsx from 'clsx'
|
||||
import { Container } from './Container'
|
||||
import { Button } from './Button'
|
||||
|
||||
|
||||
function NavLinks() {
|
||||
let [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
|
||||
let timeoutRef = useRef<number | null>(null)
|
||||
|
||||
return (
|
||||
<>
|
||||
{[
|
||||
['Home', '/'],
|
||||
['Cloud', '/cloud'],
|
||||
['Network', '/network'],
|
||||
['Agents', '/agents'],
|
||||
].map(([label, href], index) => (
|
||||
<Link
|
||||
key={label}
|
||||
to={href}
|
||||
className={clsx(
|
||||
'relative rounded-lg px-3 py-2 text-sm text-black transition-colors delay-150 hover:text-cyan-500 hover:delay-0',
|
||||
)}
|
||||
onMouseEnter={() => {
|
||||
if (timeoutRef.current) {
|
||||
window.clearTimeout(timeoutRef.current)
|
||||
}
|
||||
setHoveredIndex(index)
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
timeoutRef.current = window.setTimeout(() => {
|
||||
setHoveredIndex(null)
|
||||
}, 200)
|
||||
}}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{hoveredIndex === index && (
|
||||
<motion.span
|
||||
className="absolute inset-0 rounded-lg bg-white/50"
|
||||
layoutId="hoverBackground"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { duration: 0.15 } }}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.15 },
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<span className="relative z-10">{label}</span>
|
||||
</Link>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function Header() {
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
const [lastScrollY, setLastScrollY] = useState(0)
|
||||
|
||||
const controlHeader = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (window.scrollY > lastScrollY && window.scrollY > 100) {
|
||||
// Hides when scrolling down past 100px
|
||||
setIsVisible(false)
|
||||
} else {
|
||||
// Shows when scrolling up
|
||||
setIsVisible(true)
|
||||
}
|
||||
setLastScrollY(window.scrollY)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('scroll', controlHeader)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', controlHeader)
|
||||
}
|
||||
}
|
||||
}, [lastScrollY])
|
||||
|
||||
return (
|
||||
<motion.header
|
||||
className="fixed top-0 left-0 right-0 z-50 bg-white/90 shadow-lg ring-1 ring-gray-200"
|
||||
initial={{ y: 0, opacity: 1 }}
|
||||
animate={{ y: isVisible ? 0 : -100, opacity: isVisible ? 1 : 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
>
|
||||
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-3 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-x-5">
|
||||
<Link to="/" aria-label="Home">
|
||||
<img src="/src/images/logomark.svg" alt="Mycelium" className="h-10 w-auto" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-5">
|
||||
<NavLinks />
|
||||
</div>
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="flex items-center gap-6 max-lg:hidden">
|
||||
<Button
|
||||
to="https://threefold.info/mycelium_network/docs/"
|
||||
variant="outline"
|
||||
as="a"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Docs
|
||||
</Button>
|
||||
<Button to="/download" variant="solid" color="cyan">
|
||||
Get Mycelium
|
||||
</Button>
|
||||
<header>
|
||||
<nav>
|
||||
<Container className="relative z-50 flex justify-between py-8">
|
||||
<div className="relative z-10 flex items-center gap-16">
|
||||
<Link to="/" aria-label="Home">
|
||||
<img src="/src/images/logomark.svg" alt="Mycelium" className="h-10 w-auto" />
|
||||
</Link>
|
||||
<div className="hidden lg:flex lg:gap-10">
|
||||
<Link
|
||||
to="/"
|
||||
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||
>
|
||||
Home
|
||||
</Link>
|
||||
<Link
|
||||
to="/cloud"
|
||||
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||
>
|
||||
Cloud
|
||||
</Link>
|
||||
<Link
|
||||
to="/network"
|
||||
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||
>
|
||||
Network
|
||||
</Link>
|
||||
<Link
|
||||
to="/agents"
|
||||
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||
>
|
||||
Agents
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex items-center gap-6 max-lg:hidden">
|
||||
<Button
|
||||
to="https://threefold.info/mycelium_network/docs/"
|
||||
variant="outline"
|
||||
as="a"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Docs
|
||||
</Button>
|
||||
<Button to="/download" variant="solid" color="cyan">
|
||||
Get Mycelium
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { FloatingNav } from './ui/floating-navbar'
|
||||
import { Footer } from './Footer'
|
||||
import { Header } from './Header'
|
||||
|
||||
export function Layout() {
|
||||
const navItems = [
|
||||
{ name: 'Home', link: '/' },
|
||||
{ name: 'Cloud', link: '/cloud' },
|
||||
{ name: 'Network', link: '/network' },
|
||||
{ name: 'Agents', link: '/agents' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-white antialiased" style={{ fontFamily: 'var(--font-inter)' }}>
|
||||
<Header />
|
||||
<main>
|
||||
<main className="">
|
||||
<Outlet />
|
||||
</main>
|
||||
<Footer />
|
||||
|
||||
Reference in New Issue
Block a user