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