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 { Link } from 'react-router-dom'
|
||||||
import { AnimatePresence, motion } from 'framer-motion'
|
import { Container } from './Container'
|
||||||
import clsx from 'clsx'
|
|
||||||
import { Button } from './Button'
|
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() {
|
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 (
|
return (
|
||||||
<motion.header
|
<header>
|
||||||
className="fixed top-0 left-0 right-0 z-50 bg-white/90 shadow-lg ring-1 ring-gray-200"
|
<nav>
|
||||||
initial={{ y: 0, opacity: 1 }}
|
<Container className="relative z-50 flex justify-between py-8">
|
||||||
animate={{ y: isVisible ? 0 : -100, opacity: isVisible ? 1 : 0 }}
|
<div className="relative z-10 flex items-center gap-16">
|
||||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
<Link to="/" aria-label="Home">
|
||||||
>
|
<img src="/src/images/logomark.svg" alt="Mycelium" className="h-10 w-auto" />
|
||||||
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-3 sm:px-6 lg:px-8">
|
</Link>
|
||||||
<div className="flex items-center gap-x-5">
|
<div className="hidden lg:flex lg:gap-10">
|
||||||
<Link to="/" aria-label="Home">
|
<Link
|
||||||
<img src="/src/images/logomark.svg" alt="Mycelium" className="h-10 w-auto" />
|
to="/"
|
||||||
</Link>
|
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||||
</div>
|
>
|
||||||
<div className="flex items-center gap-x-5">
|
Home
|
||||||
<NavLinks />
|
</Link>
|
||||||
</div>
|
<Link
|
||||||
<div className="flex items-center gap-8">
|
to="/cloud"
|
||||||
<div className="flex items-center gap-6 max-lg:hidden">
|
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||||
<Button
|
>
|
||||||
to="https://threefold.info/mycelium_network/docs/"
|
Cloud
|
||||||
variant="outline"
|
</Link>
|
||||||
as="a"
|
<Link
|
||||||
target="_blank"
|
to="/network"
|
||||||
rel="noopener noreferrer"
|
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||||
>
|
>
|
||||||
Docs
|
Network
|
||||||
</Button>
|
</Link>
|
||||||
<Button to="/download" variant="solid" color="cyan">
|
<Link
|
||||||
Get Mycelium
|
to="/agents"
|
||||||
</Button>
|
className="text-base/7 tracking-tight text-gray-700 hover:text-cyan-500 transition-colors"
|
||||||
|
>
|
||||||
|
Agents
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="flex items-center gap-6">
|
||||||
</div>
|
<div className="flex items-center gap-6 max-lg:hidden">
|
||||||
</motion.header>
|
<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 { Outlet } from 'react-router-dom'
|
||||||
import { FloatingNav } from './ui/floating-navbar'
|
|
||||||
import { Footer } from './Footer'
|
import { Footer } from './Footer'
|
||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
|
|
||||||
export function Layout() {
|
export function Layout() {
|
||||||
const navItems = [
|
|
||||||
{ name: 'Home', link: '/' },
|
|
||||||
{ name: 'Cloud', link: '/cloud' },
|
|
||||||
{ name: 'Network', link: '/network' },
|
|
||||||
{ name: 'Agents', link: '/agents' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white antialiased" style={{ fontFamily: 'var(--font-inter)' }}>
|
<div className="bg-white antialiased" style={{ fontFamily: 'var(--font-inter)' }}>
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main className="">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function HomeAurora() {
|
|||||||
backgroundSize: "cover",
|
backgroundSize: "cover",
|
||||||
backgroundPosition: "center",
|
backgroundPosition: "center",
|
||||||
}}
|
}}
|
||||||
className="relative mx-auto py-24 h-screen flex flex-col items-center justify-center gap-4 px-4 max-w-5xl"
|
className="relative mx-auto pb-24 pt-0 h-screen flex flex-col items-center justify-center gap-4 px-4 max-w-5xl"
|
||||||
>
|
>
|
||||||
<div className="text-center text-gray-800">
|
<div className="text-center text-gray-800">
|
||||||
<H1>Decentralized Autonomous <span className="text-bold lg:text-8xl">Agentic Cloud.</span></H1>
|
<H1>Decentralized Autonomous <span className="text-bold lg:text-8xl">Agentic Cloud.</span></H1>
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { H1, P } from '@/components/Texts'
|
import { H1, P } from '@/components/Texts'
|
||||||
import { FadeIn } from '@/components/FadeIn'
|
|
||||||
import { Button } from '@/components/Button'
|
import { Button } from '@/components/Button'
|
||||||
|
|
||||||
export function HomeHero() {
|
export function HomeHero() {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative isolate overflow-hidden bg-white"
|
className="relative isolate overflow-hidden bg-white h-screen -z-10 flex items-center justify-center"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: 'url(/images/cloud.png)',
|
backgroundImage: 'url(/images/cloud.png)',
|
||||||
backgroundSize: 'cover',
|
backgroundSize: 'cover',
|
||||||
backgroundPosition: 'center',
|
backgroundPosition: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="mx-auto max-w-7xl px-6 py-24 lg:py-32 lg:flex lg:px-8">
|
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||||
<div className="mx-auto max-w-2xl shrink-0 lg:mx-0 lg:pt-8">
|
<div className="-mt-32 mx-auto max-w-2xl text-center">
|
||||||
<H1 color="primary" className="mt-10 text-5xl font-semibold tracking-tight text-pretty sm:text-7xl">
|
<H1 color="primary" className="text-5xl font-semibold tracking-tight text-pretty sm:text-7xl">
|
||||||
Decentralized Autonomous Agentic Cloud.
|
Decentralized Autonomous Agentic Cloud.
|
||||||
</H1>
|
</H1>
|
||||||
<P color="secondary" className="mt-8 text-lg font-medium text-pretty sm:text-xl/8">
|
<P color="secondary" className="mt-8 text-lg font-medium text-pretty sm:text-xl/8">
|
||||||
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
||||||
</P>
|
</P>
|
||||||
<div className="mt-10 flex items-center gap-x-6">
|
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||||
<Button variant="solid" color="cyan" href="#">
|
<Button variant="solid" color="cyan" href="#">
|
||||||
Get started
|
Get started
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
|
|||||||
|
|
||||||
export function Hero() {
|
export function Hero() {
|
||||||
return (
|
return (
|
||||||
<div className="overflow-hidden lg:py-32 lg:pb-0 pb-24">
|
<div className="overflow-hidden py-32">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col-reverse gap-y-16 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
|
<div className="flex flex-col-reverse gap-y-16 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
|
||||||
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
|
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
|
||||||
@@ -94,8 +94,8 @@ export function Hero() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative lg:mt-10 mt-0 lg:col-span-5 lg:row-span-2 xl:col-span-6">
|
<div className="relative lg:mt-10 mt-0 lg:col-span-5 lg:row-span-2 xl:col-span-6">
|
||||||
<BackgroundIllustration className="absolute top-4 left-1/2 h-[1026px] w-[1026px] -translate-x-1/2 stroke-gray-300/70 sm:top-16 lg:-top-12 lg:ml-12 ml-0" />
|
<BackgroundIllustration className="absolute top-4 left-1/2 h-[1026px] w-[1026px] -translate-x-1/2 stroke-gray-300/70 sm:top-16 lg:top-0 lg:ml-12 ml-0" />
|
||||||
<div className="mx-auto h-[448px] mask-[linear-gradient(to_bottom,white_60%,transparent)] lg:px-0 lg:absolute lg:-inset-x-10 lg:-top-24 lg:h-auto lg:pt-10 xl:-bottom-32">
|
<div className="mx-auto h-[448px] mask-[linear-gradient(to_bottom,white_60%,transparent)] lg:px-0 lg:absolute lg:-inset-x-10 lg:top-0 lg:h-auto lg:pt-10 xl:-bottom-32">
|
||||||
<img
|
<img
|
||||||
src={phoneFrame}
|
src={phoneFrame}
|
||||||
alt="Mycelium application demo"
|
alt="Mycelium application demo"
|
||||||
|
|||||||
Reference in New Issue
Block a user