99 lines
3.1 KiB
TypeScript
99 lines
3.1 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import Link from 'next/link'
|
|
import { AnimatePresence, motion } from 'framer-motion'
|
|
import clsx from 'clsx'
|
|
|
|
function NavLinks() {
|
|
let [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
|
|
let timeoutRef = useRef<number | null>(null)
|
|
|
|
return (
|
|
<div className="flex items-center gap-x-5">
|
|
<div className="flex items-center gap-x-5 border-l border-white/10 pl-5">
|
|
{[
|
|
['Technologies', '/#technologies'],
|
|
['Network', '/#network'],
|
|
['How it Works', '/#how-it-works'],
|
|
['Get Started', '/#get-started'],
|
|
['Contact', '/#contact'],
|
|
].map(([label, href], index) => (
|
|
<Link
|
|
key={label}
|
|
href={href}
|
|
className={clsx(
|
|
'relative rounded-lg px-3 py-2 text-sm text-black transition-colors delay-150 hover:text-gray-700 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/10"
|
|
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>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function HeaderLight() {
|
|
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-4 left-0 right-0 z-50 flex justify-center"
|
|
initial={{ y: 0, opacity: 1 }}
|
|
animate={{ y: isVisible ? 0 : -100, opacity: isVisible ? 1 : 0 }}
|
|
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
|
>
|
|
<div className="rounded-full bg-gray-50/90 px-5 py-3 shadow-lg ring-1 ring-white/10 backdrop-blur-sm">
|
|
<NavLinks />
|
|
</div>
|
|
</motion.header>
|
|
)
|
|
}
|