'use client' import { Fragment, useEffect, useId, useRef, useState } from 'react' import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react' import clsx from 'clsx' import { type MotionProps, type Variant, AnimatePresence, motion, } from 'framer-motion' import { useDebouncedCallback } from 'use-debounce' import { Eyebrow, FeatureDescription, FeatureTitle, MobileFeatureTitle, P, SectionHeader, } from '@/components/Texts' import { Container } from '@/components/Container' import reservenodeimg from '/images/cloud/reserve.png' import billingImg from '/images/cloud/billing.png' import kubeconfigImg from '/images/cloud/kubeconfig.png' interface CustomAnimationProps { isForwards: boolean changeCount: number } const features = [ { name: 'Decentralized Kubernetes', description: "Reserve a node and deploy sovereign Kubernetes clusters on decentralized infrastructure.", icon: DeviceUserIcon, screen: ReserveNodeScreen, }, { name: 'Manage Your Cluster', description: 'Manage your cluster with ease, with a simple and intuitive interface.', icon: DeviceNotificationIcon, screen: ManageClusterScreen, }, { name: 'Personalised Billings & Accounts', description: 'Easily manage your cluster billing and accounts with personalised configurations.', icon: DeviceTouchIcon, screen: PersonalisedBillingsScreen, }, ] function DeviceUserIcon(props: React.ComponentPropsWithoutRef<'svg'>) { return ( ) } function DeviceNotificationIcon(props: React.ComponentPropsWithoutRef<'svg'>) { return ( ) } function DeviceTouchIcon(props: React.ComponentPropsWithoutRef<'svg'>) { let id = useId() return ( ) } const maxZIndex = 2147483647 const bodyVariantBackwards: Variant = { opacity: 0.4, scale: 0.8, zIndex: 0, filter: 'blur(4px)', transition: { duration: 0.4 }, } const bodyAnimation: MotionProps = { initial: 'initial', animate: 'animate', exit: 'exit', variants: { initial: (custom: CustomAnimationProps) => ( custom.isForwards ? { y: '100%', zIndex: maxZIndex - custom.changeCount, transition: { duration: 0.4 }, } : bodyVariantBackwards ), animate: (custom: CustomAnimationProps) => ({ y: '0%', opacity: 1, scale: 1, zIndex: maxZIndex / 2 - custom.changeCount, filter: 'blur(0px)', transition: { duration: 0.4 }, }), exit: (custom: CustomAnimationProps) => ( custom.isForwards ? bodyVariantBackwards : { y: '100%', zIndex: maxZIndex - custom.changeCount, transition: { duration: 0.4 }, } ), }, } function ReserveNodeScreen() { return ( Mycelium Reserve Node ); } function ManageClusterScreen() { return ( Mycelium Kubeconfig ); } function PersonalisedBillingsScreen() { return ( Mycelium Billing ); } function usePrevious(value: T) { const ref = useRef() useEffect(() => { ref.current = value }, [value]) return ref.current } function CloudFeaturesDesktop() { let [changeCount, setChangeCount] = useState(0) let [selectedIndex, setSelectedIndex] = useState(0) let prevIndex = usePrevious(selectedIndex) let isForwards = prevIndex === undefined ? true : selectedIndex > prevIndex let onChange = useDebouncedCallback( (selectedIndex: number) => { setSelectedIndex(selectedIndex) setChangeCount((changeCount) => changeCount + 1) }, 100, { leading: true }, ) return ( {features.map((feature, featureIndex) => (
{featureIndex === selectedIndex && ( )}
{feature.name} {feature.description}
))}
{features.map((feature, featureIndex) => selectedIndex === featureIndex ? ( ) : null, )}
) } function CloudFeaturesMobile() { let [activeIndex, setActiveIndex] = useState(0) let slideContainerRef = useRef>(null) let slideRefs = useRef>>([]) useEffect(() => { let observer = new window.IntersectionObserver( (entries) => { for (let entry of entries) { if (entry.isIntersecting && entry.target instanceof HTMLDivElement) { setActiveIndex(slideRefs.current.indexOf(entry.target)) break } } }, { root: slideContainerRef.current, threshold: 0.6, }, ) for (let slide of slideRefs.current) { if (slide) { observer.observe(slide) } } return () => { observer.disconnect() } }, [slideContainerRef, slideRefs]) return ( <>
{features.map((feature, featureIndex) => (
ref && (slideRefs.current[featureIndex] = ref)} className="w-full flex-none snap-center px-4 sm:px-6 transition-all duration-300 ease-in-out hover:scale-105" >
{feature.name} {feature.description}
))}
{features.map((_, featureIndex) => ( ))}
) } export function CloudFeatures() { return (
Platform Overview A Decentralized Cloud that Operates Itself

Mycelium Cloud orchestrates Kubernetes clusters on the ThreeFold Grid with cryptographic certainty. Networking, storage, and orchestration are all built-in so developers can deploy critical workloads without wrestling infrastructure.

) }