feat: implement light theme version of stack section with hover animations
This commit is contained in:
@@ -7,7 +7,7 @@ import { HomeHeroLight } from '@/components/HomeHeroLight'
|
|||||||
import { HomeHeroLight2 } from '@/components/HomeHeroLight2'
|
import { HomeHeroLight2 } from '@/components/HomeHeroLight2'
|
||||||
import { HomeAbout } from '@/components/HomeAbout'
|
import { HomeAbout } from '@/components/HomeAbout'
|
||||||
import { ClickableGallery } from '@/components/ClickableGallery'
|
import { ClickableGallery } from '@/components/ClickableGallery'
|
||||||
import { StackSectionPreview } from '@/components/StackSection'
|
import { StackSectionLight } from '@/components/StackSectionLight'
|
||||||
import { Companies } from '@/components/Companies'
|
import { Companies } from '@/components/Companies'
|
||||||
import { CallToAction } from '@/components/CallToAction'
|
import { CallToAction } from '@/components/CallToAction'
|
||||||
import { ScrollDown } from '@/components/ui/ScrollDown'
|
import { ScrollDown } from '@/components/ui/ScrollDown'
|
||||||
@@ -27,7 +27,7 @@ export default function Home() {
|
|||||||
<WorldMap />
|
<WorldMap />
|
||||||
</section>
|
</section>
|
||||||
<section id="technologies">
|
<section id="technologies">
|
||||||
<StackSectionPreview />
|
<StackSectionLight />
|
||||||
</section>
|
</section>
|
||||||
<section id="deploy">
|
<section id="deploy">
|
||||||
<Steps />
|
<Steps />
|
||||||
|
|||||||
37
src/components/StackSectionLight.tsx
Normal file
37
src/components/StackSectionLight.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { StackedCubesLight } from "@/components/ui/StackedCubesLight";
|
||||||
|
import { H1, H2, P } from '@/components/Texts';
|
||||||
|
import { FadeIn } from "./FadeIn";
|
||||||
|
|
||||||
|
export function StackSectionLight() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="w-full bg-white lg:px-0 py-12 lg:py-24 px-6 relative lg:pt-32">
|
||||||
|
<div className="mx-auto max-w-7xl">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-16 items-center lg:items-center">
|
||||||
|
{/* Left Column - Text (1/3 width) */}
|
||||||
|
<div className="text-center lg:text-left lg:col-span-1 order-1 lg:order-1 pt-12">
|
||||||
|
<FadeIn>
|
||||||
|
<H2 className="" color="dark">
|
||||||
|
The Mycelium Stack
|
||||||
|
</H2>
|
||||||
|
</FadeIn>
|
||||||
|
|
||||||
|
<FadeIn>
|
||||||
|
<P className="mx-auto mt-8 max-w-3xl" color="dark">
|
||||||
|
Built with Mycelium technology, our AI infrastructure ensures unbreakable networks, complete data sovereignty, ultra-secure agent-human communication, and unhackable data storage systems.
|
||||||
|
</P>
|
||||||
|
</FadeIn>
|
||||||
|
</div>
|
||||||
|
{/* Right Column - Stacked Cubes (2/3 width) */}
|
||||||
|
<div className="lg:col-span-2 flex items-center justify-center lg:justify-start order-2 lg:order-2 mt-8 lg:mt-0">
|
||||||
|
<FadeIn>
|
||||||
|
<StackedCubesLight />
|
||||||
|
</FadeIn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ const colorVariants = {
|
|||||||
secondary: 'text-gray-200',
|
secondary: 'text-gray-200',
|
||||||
custom: 'text-[#015eff]',
|
custom: 'text-[#015eff]',
|
||||||
light: '[#fcfcfc]',
|
light: '[#fcfcfc]',
|
||||||
|
dark: 'text-gray-800',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
type TextOwnProps = {
|
type TextOwnProps = {
|
||||||
|
|||||||
131
src/components/ui/CubeLight.tsx
Normal file
131
src/components/ui/CubeLight.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
|
interface CubeProps {
|
||||||
|
title: string;
|
||||||
|
descriptionTitle: string;
|
||||||
|
description: string;
|
||||||
|
isActive: boolean;
|
||||||
|
index: number;
|
||||||
|
onHover: () => void;
|
||||||
|
onLeave: () => void;
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="507"
|
||||||
|
height="234"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 507 234"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill={`url(#cube-gradient-${index})`}
|
||||||
|
d="M491.651 144.747L287.198 227.339C265.219 236.22 241.783 236.22 219.802 227.339L15.3486 144.747C-5.11621 136.479 -5.11621 97.5191 15.3486 89.2539L219.802 6.65884C241.783 -2.21961 265.219 -2.21961 287.198 6.65884L491.651 89.2539C512.116 97.5191 512.116 136.479 491.651 144.747Z"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient
|
||||||
|
id={`cube-gradient-${index}`}
|
||||||
|
x1="185.298"
|
||||||
|
x2="185.298"
|
||||||
|
y1="-27.5515"
|
||||||
|
y2="206.448"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#E5E7EB" />
|
||||||
|
<stop offset="1" stopColor="#9CA3AF" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export function CubeLight({ title, descriptionTitle, description, isActive, index, onHover, onLeave, onClick }: CubeProps) {
|
||||||
|
return (
|
||||||
|
<div className="relative flex flex-col items-center">
|
||||||
|
<motion.div
|
||||||
|
className="relative cursor-pointer"
|
||||||
|
onMouseEnter={onHover}
|
||||||
|
onMouseLeave={onLeave}
|
||||||
|
onClick={onClick}
|
||||||
|
style={{
|
||||||
|
zIndex: 10 - index,
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
scale: isActive ? 1.05 : 1,
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 0.3,
|
||||||
|
ease: "easeOut",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* SVG Cube */}
|
||||||
|
<CubeSvg
|
||||||
|
index={index}
|
||||||
|
className="w-48 sm:w-64 lg:w-80 h-auto drop-shadow-lg opacity-80"
|
||||||
|
style={{
|
||||||
|
filter: isActive ? 'brightness(1.1) drop-shadow(0 0 15px rgba(0, 0, 0, 0.2))' : 'brightness(1)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Title overlay */}
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<h3
|
||||||
|
className="text-black text-sm lg:text-base font-medium text-center px-4 drop-shadow-sm"
|
||||||
|
style={{
|
||||||
|
transform: 'rotate(0deg) skewX(0deg)',
|
||||||
|
transformOrigin: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description with arrow line - Desktop */}
|
||||||
|
{isActive && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
className="hidden lg:block absolute left-full top-1/2 -translate-y-1/2 z-50"
|
||||||
|
>
|
||||||
|
{/* Arrow line */}
|
||||||
|
<svg
|
||||||
|
className="absolute left-0 top-1/2 -translate-y-1/2"
|
||||||
|
width="120"
|
||||||
|
height="2"
|
||||||
|
viewBox="0 0 120 2"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<line
|
||||||
|
x1="0"
|
||||||
|
y1="1"
|
||||||
|
x2="120"
|
||||||
|
y2="1"
|
||||||
|
stroke="black"
|
||||||
|
strokeWidth="1"
|
||||||
|
opacity="0.6"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{/* Description text */}
|
||||||
|
<div className="ml-32 w-80">
|
||||||
|
<h4 className="text-black text-base font-semibold mb-2">
|
||||||
|
{descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<p className="text-gray-800 text-sm leading-relaxed font-light">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Description for Mobile - Below cube */}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
95
src/components/ui/StackedCubesLight.tsx
Normal file
95
src/components/ui/StackedCubesLight.tsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { CubeLight } from "@/components/ui/CubeLight"
|
||||||
|
|
||||||
|
const stackData = [
|
||||||
|
{
|
||||||
|
id: "agent",
|
||||||
|
title: "Agent Layer",
|
||||||
|
descriptionTitle: "Your sovereign agent with private memory and permissioned data access—always under your control.",
|
||||||
|
description:
|
||||||
|
"Choose from a wide library of open-source LLMs, paired with built-in semantic search and retrieval.\nIt coordinates across people, apps, and other agents to plan, create, and execute.\nIt operates inside a compliant legal & financial sandbox, ready for real-world transactions and operations.\nMore than just an assistant—an intelligent partner that learns and does your way.",
|
||||||
|
position: "top",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "network",
|
||||||
|
title: "Network Layer",
|
||||||
|
descriptionTitle: "A global, end-to-end encrypted overlay that simply doesn’t break.",
|
||||||
|
description:
|
||||||
|
"Shortest-path routing moves your traffic the fastest way, every time.\nInstant discovery with integrated DNS, semantic search, and indexing.\nA distributed CDN and edge delivery keep content available and tamper-resistant worldwide.\nBuilt-in tool services and secure coding sandboxes—seamless on phones, desktops, and edge.",
|
||||||
|
position: "middle",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "cloud",
|
||||||
|
title: "Cloud Layer",
|
||||||
|
descriptionTitle: "An autonomous, stateless OS that enforces pre-deterministic deployments you define.",
|
||||||
|
description:
|
||||||
|
"Workloads are cryptographically bound to your private key—location and access are yours.\nNo cloud vendor or middleman in the path: end-to-end ownership and isolation by default.\nGeo-aware placement delivers locality, compliance, and ultra-low latency where it matters.\nEncrypted, erasure-coded storage, decentralized compute and GPU on demand—including LLMs.",
|
||||||
|
position: "bottom",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function StackedCubesLight() {
|
||||||
|
const [active, setActive] = useState<string | null>("agent");
|
||||||
|
const [selectedForMobile, setSelectedForMobile] = useState<string | null>("agent");
|
||||||
|
|
||||||
|
const handleCubeClick = (id: string) => {
|
||||||
|
setSelectedForMobile(prev => (prev === id ? null : id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedMobileLayer = stackData.find(layer => layer.id === selectedForMobile);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div
|
||||||
|
className="relative w-full flex items-center justify-center lg:justify-center min-h-[450px] lg:min-h-[400px]"
|
||||||
|
onMouseLeave={() => setActive("agent")}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="relative lg:pl-0 pl-6 h-[300px] lg:h-[400px] w-64 sm:w-80 lg:w-96 scale-120 lg:scale-100"
|
||||||
|
animate={{ y: ["-8px", "8px"] }}
|
||||||
|
transition={{
|
||||||
|
duration: 4,
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatType: "reverse",
|
||||||
|
ease: "easeInOut",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{stackData.map((layer, index) => (
|
||||||
|
<div
|
||||||
|
key={layer.id}
|
||||||
|
className="absolute"
|
||||||
|
style={{
|
||||||
|
top: `calc(${index * 30}% - ${index * 10}px)`,
|
||||||
|
zIndex: active === layer.id ? 20 : 10 - index,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CubeLight
|
||||||
|
title={layer.title}
|
||||||
|
descriptionTitle={layer.descriptionTitle}
|
||||||
|
description={layer.description}
|
||||||
|
isActive={active === layer.id}
|
||||||
|
index={index}
|
||||||
|
onHover={() => setActive(layer.id)}
|
||||||
|
onLeave={() => {}}
|
||||||
|
onClick={() => handleCubeClick(layer.id)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
{selectedMobileLayer && (
|
||||||
|
<div className="lg:hidden w-full max-w-md p-6 -mt-8 bg-gray-200/50 rounded-lg">
|
||||||
|
<h4 className="text-black text-lg font-semibold mb-2 text-center">
|
||||||
|
{selectedMobileLayer.descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<p className="text-gray-700 text-sm leading-relaxed text-center">
|
||||||
|
{selectedMobileLayer.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user