feat: redesign cloud features section with new UI and content

- Replaced mobile phone mockups with full-width desktop screenshots for cloud platform features
- Updated feature descriptions to focus on cloud/Kubernetes capabilities instead of network features
- Changed section layout to improve desktop view with left-aligned feature tabs
- Removed unused phone frame component and related mobile UI elements
- Updated image assets from jpg to png format and reorganized image paths
- Reordered page
This commit is contained in:
2025-10-31 04:40:14 +01:00
parent 26ae2f156a
commit bfe3c1e4bd
8 changed files with 61 additions and 55 deletions

View File

@@ -11,7 +11,6 @@ import {
} from 'framer-motion'
import { useDebouncedCallback } from 'use-debounce'
import { AppScreen } from '../network/AppScreen'
import {
Eyebrow,
FeatureDescription,
@@ -23,10 +22,9 @@ import {
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
import connectorImg from '@/images/connector.png'
import peersImg from '@/images/peers.png'
import settingImg from '@/images/setting.png'
import { PhoneFrame } from '@/components/PhoneFrame'
import reservenodeimg from '/images/cloud/reserve.png'
import billingImg from '/images/cloud/billing.png'
import kubeconfigImg from '/images/cloud/kubeconfig.png'
interface CustomAnimationProps {
@@ -36,25 +34,25 @@ interface CustomAnimationProps {
const features = [
{
name: 'Mycelium Connector',
name: 'Decentralized Kubernetes',
description:
"Start (and stop) your Mycelium connector to gain access to sites, apps, and workloads available exclusively on the Mycelium Network. View statistics around peers and traffic.",
"Reserve a node and deploy sovereign Kubernetes clusters on decentralized infrastructure.",
icon: DeviceUserIcon,
screen: InviteScreen,
screen: ReserveNodeScreen,
},
{
name: 'Mycelium Peers',
name: 'Manage Your Cluster',
description:
'Search and discover active peers on the Mycelium Network, or add your own.',
'Manage your cluster with ease, with a simple and intuitive interface.',
icon: DeviceNotificationIcon,
screen: StocksScreen,
screen: ManageClusterScreen,
},
{
name: 'Network Setting',
name: 'Personalised Billings & Accounts',
description:
'Find version and network information and trigger light or dark mode.',
'Easily manage your cluster billing and accounts with personalised configurations.',
icon: DeviceTouchIcon,
screen: InvestScreen,
screen: PersonalisedBillingsScreen,
},
]
@@ -182,28 +180,40 @@ const bodyAnimation: MotionProps = {
}
function InviteScreen() {
function ReserveNodeScreen() {
return (
<AppScreen className="w-full">
<img src={connectorImg} alt="Mycelium Connector" width="366" height="732" className="-mt-8" />
</AppScreen>
)
<img
src={reservenodeimg}
alt="Mycelium Reserve Node"
width={2432}
height={1442}
className="w-4xl max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-240 md:-ml-4 lg:ml-0"
/>
);
}
function StocksScreen() {
function ManageClusterScreen() {
return (
<AppScreen className="w-full">
<img src={peersImg} alt="Mycelium Peers" width="366" height="732" className="-mt-8" />
</AppScreen>
)
<img
src={kubeconfigImg}
alt="Mycelium Kubeconfig"
width={2432}
height={1442}
className="w-4xl max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-240 md:-ml-4 lg:ml-0"
/>
);
}
function InvestScreen() {
function PersonalisedBillingsScreen() {
return (
<AppScreen className="w-full">
<img src={settingImg} alt="Mycelium Settings" width="366" height="732" className="-mt-8" />
</AppScreen>
)
<img
src={billingImg}
alt="Mycelium Billing"
width={2432}
height={1442}
className="w-4xl max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-240 md:-ml-4 lg:ml-0"
/>
);
}
function usePrevious<T>(value: T) {
@@ -216,7 +226,7 @@ function usePrevious<T>(value: T) {
return ref.current
}
function FeaturesDesktop() {
function CloudFeaturesDesktop() {
let [changeCount, setChangeCount] = useState(0)
let [selectedIndex, setSelectedIndex] = useState(0)
let prevIndex = usePrevious(selectedIndex)
@@ -238,12 +248,12 @@ function FeaturesDesktop() {
onChange={onChange}
vertical
>
<TabList className="z-10 order-last col-span-6 space-y-6">
<TabList className="z-10 col-span-6 space-y-6 pl-4 sm:pl-6 lg:pl-8">
{features.map((feature, featureIndex) => (
<div
key={feature.name}
className={clsx(
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30',
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30 ml-16',
selectedIndex === featureIndex
? 'outline-cyan-500'
: 'outline-transparent hover:outline-cyan-500',
@@ -252,7 +262,7 @@ function FeaturesDesktop() {
{featureIndex === selectedIndex && (
<motion.div
layoutId="activeBackground"
className="absolute inset-0 bg-gray-800"
className="absolute inset-0 bg-gray-800 "
initial={{ borderRadius: 16 }}
/>
)}
@@ -271,11 +281,11 @@ function FeaturesDesktop() {
</div>
))}
</TabList>
<div className="relative col-span-6">
<div className="relative col-span-6 overflow-hidden">
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<CircleBackground id="primaryfeatures_desktop_circle" color="#13B5C8" className="animate-spin-slower" />
</div>
<PhoneFrame className="z-10 mx-auto w-full max-w-[366px]">
<div className="z-10 mx-auto w-full max-w-[366px]">
<TabPanels as={Fragment}>
<AnimatePresence
initial={false}
@@ -296,13 +306,13 @@ function FeaturesDesktop() {
)}
</AnimatePresence>
</TabPanels>
</PhoneFrame>
</div>
</div>
</TabGroup>
)
}
function FeaturesMobile() {
function CloudFeaturesMobile() {
let [activeIndex, setActiveIndex] = useState(0)
let slideContainerRef = useRef<React.ElementRef<'div'>>(null)
let slideRefs = useRef<Array<React.ElementRef<'div'>>>([])
@@ -361,9 +371,9 @@ function FeaturesMobile() {
className={featureIndex % 2 === 1 ? 'rotate-180' : undefined}
/>
</div>
<PhoneFrame className="relative mx-auto w-full max-w-[366px]">
<div className="relative mx-auto w-full max-w-[366px]">
<feature.screen />
</PhoneFrame>
</div>
<div className="absolute inset-x-0 bottom-0 bg-gray-800/95 p-6 backdrop-blur-sm sm:p-10">
<feature.icon className="h-8 w-8" />
<MobileFeatureTitle color="white" className="mt-6">
@@ -405,29 +415,27 @@ function FeaturesMobile() {
export function CloudFeatures() {
return (
<section
id="howitworks"
id="overview"
aria-label="Features for investing all your money"
className="bg-gray-900 py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-3xl">
<Eyebrow color="accent">How It Works</Eyebrow>
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-none">
<Eyebrow color="accent">Platform Overview</Eyebrow>
<SectionHeader color="white" className="mt-2">
How Mycelium Operates
A Decentralized Cloud that Operates Itself
</SectionHeader>
<P color="light" className="mt-6">
Mycelium, like its natural namesake, thrives on decentralization,
efficiency, and security, making it a truly powerful force in the world
of decentralized networks.
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.
</P>
</div>
</Container>
<div className="hidden md:mt-20 md:block">
<CloudFeaturesDesktop />
</div>
<div className="mt-16 md:hidden">
<FeaturesMobile />
<CloudFeaturesMobile />
</div>
<Container className="hidden md:mt-20 md:block">
<FeaturesDesktop />
</Container>
</section>
)
}

View File

@@ -1,5 +1,4 @@
import { AnimatedSection } from '../../components/AnimatedSection'
import { CloudHero } from './CloudHero'
import { CloudOverview } from './CloudOverview'
import { CloudArchitecture } from './CloudArchitecture'
import { CloudFeatures } from './CloudFeatures'
@@ -17,14 +16,13 @@ export default function CloudPage() {
<CloudHeroNew />
</AnimatedSection>
<AnimatedSection>
<CloudOverview />
<CloudFeatures />
</AnimatedSection>
<AnimatedSection>
<CloudArchitecture />
</AnimatedSection>
<AnimatedSection>
<CloudFeatures />
</AnimatedSection>
<AnimatedSection>
<CloudGettingStarted />
</AnimatedSection>