This commit is contained in:
2025-09-18 20:21:48 +02:00
parent f5ab743987
commit cde6c90033
8 changed files with 193 additions and 192 deletions

View File

@@ -1,10 +1,10 @@
"use client"; "use client";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { H1, H2, H3, H4, P, CT, CP, NL } from "@/components/Texts"; import { H2, P } from "@/components/Texts";
import React, { useRef } from "react"; import React from "react";
import { BentoGrid, BentoGridItem } from "@/components/ui/bento-grid"; import { BentoGrid, MotionBentoGridItem } from "@/components/ui/bento-grid";
import { motion, AnimatePresence, useInView } from 'framer-motion' import { FadeIn } from "./FadeIn";
const items = [ const items = [
{ {
@@ -53,41 +53,36 @@ const items = [
]; ];
export function BentoReviews() { export function BentoReviews() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
return ( return (
<div ref={ref}> <div>
<div className="relative isolate pt-24 pb-12 bg-black text-center w-full"> <div className="relative isolate pt-24 pb-12 bg-black text-center w-full">
<motion.div <FadeIn transition={{ duration: 0.8, delay: 0.1 }}>
initial={{ opacity: 0, y: 20 }} <div className="mx-auto max-w-5xl">
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
transition={{ duration: 0.8, delay: 0.1 }}
className="mx-auto max-w-5xl"
>
<H2 className="text-center">Mycelium Technologies</H2> <H2 className="text-center">Mycelium Technologies</H2>
</motion.div> </div>
<motion.div </FadeIn>
initial={{ opacity: 0, y: 20 }} <FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} <div className="mx-auto max-w-4xl mt-6 mb-8">
transition={{ duration: 0.8, delay: 0.2 }}
className="mx-auto max-w-4xl mt-6 mb-8"
>
<P className="text-center" color="primary"> <P className="text-center" color="primary">
A robust infrastructure layer for autonomous AI agents, our technology stack A robust infrastructure layer for autonomous AI agents, our technology stack
delivers a secure, efficient, and intuitive platform for deploying and managing AI agents at scale. delivers a secure, efficient, and intuitive platform for deploying and managing AI agents at scale.
</P> </P>
</motion.div> </div>
</FadeIn>
</div> </div>
<BentoGrid className="max-w-8xl px-12 pb-12 lg:grid-cols-3"> <BentoGrid className="max-w-8xl px-12 pb-12 lg:grid-cols-3">
{items.map((item, i) => ( {items.map((item, i) => (
<BentoGridItem <MotionBentoGridItem
key={i} key={i}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false, margin: '0px 0px -100px 0px' }}
transition={{ duration: 0.8, delay: 0.3 + i * 0.1 }}
className={cn(i === 3 || i === 6 ? "md:col-span-2" : "", "h-full")}
title={item.title} title={item.title}
subtitle={item.subtitle} subtitle={item.subtitle}
description={item.description} description={item.description}
video={item.video} video={item.video}
className={i === 3 || i === 6 ? "md:col-span-2" : ""}
/> />
))} ))}
</BentoGrid> </BentoGrid>

View File

@@ -1,6 +1,7 @@
import { CircleBackground } from '@/components/CircleBackground' import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container' import { Container } from '@/components/Container'
import { Button } from '@/components/Button' import { Button } from '@/components/Button'
import { FadeIn } from '@/components/FadeIn'
export function CallToAction() { export function CallToAction() {
return ( return (
@@ -22,6 +23,7 @@ export function CallToAction() {
<CircleBackground color="#fff" className="animate-spin-slower" /> <CircleBackground color="#fff" className="animate-spin-slower" />
</div> </div>
<Container className="relative z-20"> <Container className="relative z-20">
<FadeIn>
<div className="mx-auto max-w-md sm:text-center"> <div className="mx-auto max-w-md sm:text-center">
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl"> <h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
Decentralized AI Agents that are Truly Yours Decentralized AI Agents that are Truly Yours
@@ -39,6 +41,7 @@ export function CallToAction() {
</Button> </Button>
</div> </div>
</div> </div>
</FadeIn>
</Container> </Container>
</section> </section>
) )

View File

@@ -2,11 +2,12 @@
import { useEffect, useMemo, useState, useRef } from 'react' import { useEffect, useMemo, useState, useRef } from 'react'
import Image from 'next/image' import Image from 'next/image'
import { motion, AnimatePresence, useInView } from 'framer-motion' import { motion, AnimatePresence } from 'framer-motion'
import { wrap } from 'popmotion' import { wrap } from 'popmotion'
import { Button } from '@/components/Button'; import { Button } from '@/components/Button';
import { H2, P, H4, CT, CP } from '@/components/Texts'; import { H2, P, CT } from '@/components/Texts';
import { TypeAnimation } from 'react-type-animation' import { TypeAnimation } from 'react-type-animation'
import { FadeIn } from './FadeIn';
const galleryItems = [ const galleryItems = [
{ text: 'Navigate and interact with any web interface', image: '/images/gallery/interface.jpg', width: 448, height: 277 }, { text: 'Navigate and interact with any web interface', image: '/images/gallery/interface.jpg', width: 448, height: 277 },
@@ -33,8 +34,6 @@ const AUTOPLAY_MS = 3200
export function ClickableGallery() { export function ClickableGallery() {
const [active, setActive] = useState(0) const [active, setActive] = useState(0)
const [hovering, setHovering] = useState(false) const [hovering, setHovering] = useState(false)
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
// autoplay // autoplay
useEffect(() => { useEffect(() => {
@@ -52,40 +51,40 @@ export function ClickableGallery() {
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1)) const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
return ( return (
<div ref={ref}> <div>
<div className="relative isolate pt-8 pb-0 bg-transparent text-center w-full"> <div className="relative isolate pt-8 pb-0 bg-transparent text-center w-full">
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.1 }} className="mx-auto max-w-5xl"> <FadeIn transition={{ duration: 0.8, delay: 0.1 }}>
<div className="mx-auto max-w-5xl">
<H2 className="text-center">One Agent, Endless Possibilities.</H2> <H2 className="text-center">One Agent, Endless Possibilities.</H2>
</motion.div> </div>
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.2 }} className="mx-auto max-w-4xl mt-6"> </FadeIn>
<FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
<div className="mx-auto max-w-4xl mt-6">
<P className="text-center" color="primary"> <P className="text-center" color="primary">
The future isnt about more tools. Its about one intelligent partner that can do it all. This is your gateway to creativity, automation, and discovery. The future isnt about more tools. Its about one intelligent partner that can do it all. This is your gateway to creativity, automation, and discovery.
</P> </P>
</motion.div>
</div> </div>
<motion.section </FadeIn>
initial={{ opacity: 0 }} </div>
animate={isInView ? { opacity: 1 } : { opacity: 0 }} <FadeIn transition={{ duration: 1, delay: 0.4 }}>
transition={{ duration: 1, delay: 0.4 }} <section
className="relative w-full flex items-center justify-center overflow-hidden bg-transparent -mt-8 pt-0 pb-0" className="relative w-full flex items-center justify-center overflow-hidden bg-transparent -mt-8 pt-0 pb-0"
onMouseEnter={() => setHovering(true)} onMouseEnter={() => setHovering(true)}
onMouseLeave={() => setHovering(false)} onMouseLeave={() => setHovering(false)}
> >
<div className="relative w-full max-w-[1800px] h-[500px]" style={{ perspective: '1600px' }}> <div className="relative w-full max-w-[1800px] h-[500px]" style={{ perspective: '1600px' }}>
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}> <div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
<AnimatePresence initial={false}> <AnimatePresence initial={false}>
{indices.map((idx, i) => { {indices.map((idx, i) => {
const distance = i - VISIBLE const distance = i - VISIBLE;
const item = galleryItems[idx] const item = galleryItems[idx];
const x = distance * GAP const x = distance * GAP;
const z = -Math.abs(distance) * DEPTH const z = -Math.abs(distance) * DEPTH;
const r = distance * ROT_Y const r = distance * ROT_Y;
const s = 1 - Math.abs(distance) * SCALE_DROP const s = 1 - Math.abs(distance) * SCALE_DROP;
const o = distance === 0 ? 1 : 0.80 const o = distance === 0 ? 1 : 0.80;
const zIndex = 100 - Math.abs(distance) const zIndex = 100 - Math.abs(distance);
return ( return (
<motion.div <motion.div
@@ -102,9 +101,7 @@ export function ClickableGallery() {
transition={{ type: 'spring', stiffness: 220, damping: 26 }} transition={{ type: 'spring', stiffness: 220, damping: 26 }}
onClick={() => setActive(idx)} onClick={() => setActive(idx)}
> >
<div <div className="relative bg-black flex items-center justify-center">
className="relative bg-black flex items-center justify-center"
>
<Image <Image
src={item.image} src={item.image}
alt={item.text} alt={item.text}
@@ -115,10 +112,11 @@ export function ClickableGallery() {
/> />
</div> </div>
</motion.div> </motion.div>
) );
})} })}
</AnimatePresence> </AnimatePresence>
</div> </div>
</div>
{/* Arrows */} {/* Arrows */}
<div className="absolute inset-y-0 left-8 flex items-center z-50"> <div className="absolute inset-y-0 left-8 flex items-center z-50">
@@ -157,8 +155,8 @@ export function ClickableGallery() {
</Button> </Button>
</div> </div>
</div> </div>
</section>
</FadeIn>
</div> </div>
</motion.section> );
</div>
)
} }

24
src/components/FadeIn.tsx Normal file
View File

@@ -0,0 +1,24 @@
'use client'
import { motion, Transition } from 'framer-motion'
import React from 'react'
type FadeInProps = {
children: React.ReactNode
transition?: Transition
className?: string
}
export function FadeIn({ children, transition, className }: FadeInProps) {
return (
<motion.div
className={className}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false, margin: '0px 0px -100px 0px' }}
transition={transition || { duration: 0.5 }}
>
{children}
</motion.div>
)
}

View File

@@ -6,6 +6,7 @@ import { Container } from '@/components/Container'
import { TextField } from '@/components/Fields' import { TextField } from '@/components/Fields'
import { Logomark } from '@/components/Logo' import { Logomark } from '@/components/Logo'
import { NavLinks } from '@/components/NavLinks' import { NavLinks } from '@/components/NavLinks'
import { FadeIn } from '@/components/FadeIn'
import qrCode from '@/images/qr-code.svg' import qrCode from '@/images/qr-code.svg'
function QrCodeBorder(props: React.ComponentPropsWithoutRef<'svg'>) { function QrCodeBorder(props: React.ComponentPropsWithoutRef<'svg'>) {
@@ -23,6 +24,7 @@ function QrCodeBorder(props: React.ComponentPropsWithoutRef<'svg'>) {
export function Footer() { export function Footer() {
return ( return (
<footer id="footer" className="border-t border-gray-800"> <footer id="footer" className="border-t border-gray-800">
<FadeIn>
<Container> <Container>
<div className="flex flex-col items-start justify-between gap-y-12 pt-12 pb-6 lg:flex-row lg:items-center lg:py-12"> <div className="flex flex-col items-start justify-between gap-y-12 pt-12 pb-6 lg:flex-row lg:items-center lg:py-12">
<div> <div>
@@ -76,6 +78,7 @@ export function Footer() {
</p> </p>
</div> </div>
</Container> </Container>
</FadeIn>
</footer> </footer>
) )
} }

View File

@@ -1,63 +1,41 @@
"use client"; "use client";
import { StackedCubes } from "@/components/ui/StackedCubes"; import { StackedCubes } from "@/components/ui/StackedCubes";
import { Button } from "@/components/Button";
import { motion, useInView } from 'framer-motion';
import { H2, P } from '@/components/Texts'; import { H2, P } from '@/components/Texts';
import { useRef } from "react"; import { FadeIn } from "./FadeIn";
export function StackSectionPreview() { export function StackSectionPreview() {
const ref = useRef(null);
const isInView = useInView(ref);
return ( return (
<section ref={ref} className="w-full bg-transparent lg:px-0 py-24 px-6 relative"> <section className="w-full bg-transparent lg:px-0 py-24 px-6 relative">
{/* Gradient Blob Component */} {/* Gradient Blob Component */}
<motion.div <div
initial={{ opacity: 0 }}
animate={isInView ? { opacity: 0.4 } : { opacity: 0 }}
transition={{ duration: 1, delay: 0.1 }}
className="absolute w-[400px] h-[200px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] bottom-[200px] left-[-150px] z-0" className="absolute w-[400px] h-[200px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] bottom-[200px] left-[-150px] z-0"
/> />
<motion.div <div
initial={{ opacity: 0 }}
animate={isInView ? { opacity: 0.5 } : { opacity: 0 }}
transition={{ duration: 1, delay: 0.15 }}
className="absolute w-[200px] h-[100px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] top-[200px] right-[-150px] z-0" className="absolute w-[200px] h-[100px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] top-[200px] right-[-150px] z-0"
/> />
<div className="mx-auto max-w-7xl"> <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-start"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-16 items-center lg:items-start">
{/* Left Column - Text (1/3 width) */} {/* Left Column - Text (1/3 width) */}
<div className="text-left lg:text-left lg:col-span-1 order-1 lg:order-1"> <div className="text-left lg:text-left lg:col-span-1 order-1 lg:order-1">
<motion.div <FadeIn>
initial={{ opacity: 0, y: 30 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
transition={{ duration: 0.8, delay: 0.2 }}
>
<H2 className=""> <H2 className="">
The Mycelium Stack The Mycelium Stack
</H2> </H2>
</motion.div> </FadeIn>
<motion.div <FadeIn>
initial={{ opacity: 0, y: 30 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
transition={{ duration: 0.8, delay: 0.6 }}
>
<P className="mx-auto mt-8 max-w-3xl" color="light"> <P className="mx-auto mt-8 max-w-3xl" color="light">
Built with Mycelium technology, our AI infrastructure ensures unbreakable networks, complete data sovereignty, ultra-secure agent-human communication, and unhackable data storage systems. Built with Mycelium technology, our AI infrastructure ensures unbreakable networks, complete data sovereignty, ultra-secure agent-human communication, and unhackable data storage systems.
</P> </P>
</motion.div> </FadeIn>
</div> </div>
{/* Right Column - Stacked Cubes (2/3 width) */} {/* 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"> <div className="lg:col-span-2 flex items-center justify-center lg:justify-start order-2 lg:order-2">
<motion.div <FadeIn>
initial={{ opacity: 0, y: 30 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
transition={{ duration: 0.8, delay: 0.3 }}
>
<StackedCubes /> <StackedCubes />
</motion.div> </FadeIn>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,7 +7,7 @@ const colorVariants = {
primary: 'text-[#fffff]', primary: 'text-[#fffff]',
secondary: 'text-gray-200', secondary: 'text-gray-200',
custom: 'text-[#015eff]', custom: 'text-[#015eff]',
light: 'text-white', light: '[#fcfcfc]',
} as const } as const
type TextOwnProps = { type TextOwnProps = {

View File

@@ -1,6 +1,8 @@
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { H1, H2, H3, H4, P, CT, CP, NL } from "@/components/Texts"; import { CT, CP } from "@/components/Texts";
import Image from 'next/image'; import Image from 'next/image';
import React from 'react';
import { motion } from 'framer-motion';
export const BentoGrid = ({ export const BentoGrid = ({
className, className,
@@ -21,23 +23,17 @@ export const BentoGrid = ({
); );
}; };
export const BentoGridItem = ({ export const BentoGridItem = React.forwardRef<HTMLDivElement, {
className,
title,
subtitle,
description,
img,
video,
}: {
className?: string; className?: string;
title?: string | React.ReactNode; title?: string | React.ReactNode;
subtitle?: string | React.ReactNode; subtitle?: string | React.ReactNode;
description?: string | React.ReactNode; description?: string | React.ReactNode;
img?: string; img?: string;
video?: string; video?: string;
}) => { }>(({ className, title, subtitle, description, img, video }, ref) => {
return ( return (
<div <div
ref={ref}
className={cn( className={cn(
"group/bento shadow-input row-span-1 flex flex-col justify-between rounded-xl border border-black bg-black/10 backdrop-blur-md transition-all duration-300 ease-in-out hover:scale-105 hover:border-black hover:bg-black/40", "group/bento shadow-input row-span-1 flex flex-col justify-between rounded-xl border border-black bg-black/10 backdrop-blur-md transition-all duration-300 ease-in-out hover:scale-105 hover:border-black hover:bg-black/40",
className, className,
@@ -64,4 +60,8 @@ export const BentoGridItem = ({
</div> </div>
</div> </div>
); );
}; });
BentoGridItem.displayName = 'BentoGridItem';
export const MotionBentoGridItem = motion(BentoGridItem);