feat: enhance UI with hover effects, animations and add download links

This commit is contained in:
2025-10-15 16:08:31 +02:00
parent 5d37cb4b3b
commit e598e2ffb1
7 changed files with 89 additions and 41 deletions

View File

@@ -11,6 +11,7 @@ export function About() {
> >
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"> <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<CircleBackground color="#fff" className="animate-spin-slower" /> <CircleBackground color="#fff" className="animate-spin-slower" />
<CircleBackground color="#06b6d4" className="animate-spin-reverse-slower" />
</div> </div>
<Container className="relative"> <Container className="relative">
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-3xl text-center">

View File

@@ -1,18 +1,36 @@
import { CodeBracketIcon } from '@heroicons/react/24/outline' import {
BookOpenIcon,
LifebuoyIcon,
ChatBubbleOvalLeftEllipsisIcon,
UserGroupIcon,
} from '@heroicons/react/24/outline';
const features = [ const features = [
{ {
name: 'Documentation', name: 'Documentation',
description: 'Documentation for Mycelium.', description: 'Documentation for Mycelium.',
href: 'https://threefold.info/mycelium_network/docs/',
icon: BookOpenIcon,
},
{
name: 'Support',
description: 'Talk to an expert.',
href: 'https://threefoldfaq.crisp.help/en/',
icon: LifebuoyIcon,
}, },
{ name: 'Support', description: 'Talk to an expert.' },
{ {
name: 'Forum', name: 'Forum',
description: 'Forum for all your questions.', description: 'Forum for all your questions.',
href: 'https://forum.threefold.io/',
icon: ChatBubbleOvalLeftEllipsisIcon,
}, },
{ name: 'Community', description: 'Join our Developers community on telegram.' }, {
name: 'Community',
] description: 'Join our Developers community on telegram.',
href: 'https://t.me/threefoldtesting',
icon: UserGroupIcon,
},
];
export function DevHub() { export function DevHub() {
return ( return (
@@ -30,22 +48,26 @@ export function DevHub() {
</div> </div>
<dl className="col-span-3 grid grid-cols-1 gap-8 sm:grid-cols-2"> <dl className="col-span-3 grid grid-cols-1 gap-8 sm:grid-cols-2">
{features.map((feature) => ( {features.map((feature) => (
<div key={feature.name} className="rounded-2xl border border-gray-700 p-6"> <a
<div className="flex items-center gap-x-3"> key={feature.name}
<CodeBracketIcon href={feature.href}
target="_blank"
rel="noopener noreferrer"
className="block rounded-2xl border border-gray-700 p-6 shadow-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20 hover:bg-gray-800"
>
<feature.icon
aria-hidden="true" aria-hidden="true"
className="h-6 w-6 flex-none text-cyan-500" className="h-6 w-6 flex-none text-cyan-500 mb-4"
/> />
<dt className="flex-auto font-semibold text-white"> <dt className="font-semibold text-white">
{feature.name} {feature.name}
</dt> </dt>
</div> <dd className="mt-2 text-gray-400">{feature.description}</dd>
<dd className="mt-4 text-gray-400">{feature.description}</dd> </a>
</div>
))} ))}
</dl> </dl>
</div> </div>
</div> </div>
</div> </div>
) );
} }

View File

@@ -1,4 +1,7 @@
'use client'
import Image from 'next/image'; import Image from 'next/image';
import { motion } from 'framer-motion';
import appleIcon from '@/images/apple.svg'; import appleIcon from '@/images/apple.svg';
import windowsIcon from '@/images/windows.svg'; import windowsIcon from '@/images/windows.svg';
import androidIcon from '@/images/android.svg'; import androidIcon from '@/images/android.svg';
@@ -36,22 +39,32 @@ export default function DownloadHero() {
<div className=" py-16 sm:py-32"> <div className=" py-16 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8"> <div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl lg:mx-0"> <div className="mx-auto max-w-2xl lg:mx-0">
<h2 className="text-5xl lg:text-6xl font-medium tracking-tight text-gray-900"> <motion.h2
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="text-5xl lg:text-6xl font-medium tracking-tight text-gray-900"
>
Download Mycelium Download Mycelium
</h2> </motion.h2>
<p className="mt-6 text-lg/8 text-gray-600"> <motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="mt-6 text-lg/8 text-gray-600"
>
Get Mycelium for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized networkseamlessly and efficiently. Not sure how it works?{' '} Get Mycelium for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized networkseamlessly and efficiently. Not sure how it works?{' '}
<a href="https://threefold.info/mycelium_network/docs/" className="text-cyan-500 hover:text-cyan-600 font-semibold underline"> <a href="https://threefold.info/mycelium_network/docs/" className="text-cyan-500 hover:text-cyan-600 font-semibold underline">
Read the manual. Read the manual.
</a> </a>
</p> </motion.p>
</div> </div>
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none"> <div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none">
<dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 lg:max-w-none md:grid-cols-2 lg:grid-cols-4"> <dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 lg:max-w-none md:grid-cols-2 lg:grid-cols-4">
{features.map((feature) => ( {features.map((feature) => (
<div <div
key={feature.name} key={feature.name}
className="flex flex-col rounded-lg border border-gray-200 p-8 shadow-sm transition-all duration-300 ease-in-out hover:bg-gray-50 hover:shadow-md hover:scale-105" className="flex flex-col rounded-lg border border-gray-200 p-8 shadow-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
> >
<dt className="text-base/7 font-semibold text-gray-900"> <dt className="text-base/7 font-semibold text-gray-900">
<div className="mb-6 flex h-10 w-10 items-center justify-center"> <div className="mb-6 flex h-10 w-10 items-center justify-center">

View File

@@ -9,17 +9,17 @@ export function Features() {
<section id="features" className=" py-24"> <section id="features" className=" py-24">
<div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8"> <div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8">
<h2 className="text-base/7 font-semibold text-cyan-500">Core Components</h2> <h2 className="text-base/7 font-semibold text-cyan-500">Core Components</h2>
<p className="mt-2 max-w-4xl text-3xl lg:text-4xl font-medium tracking-tight text-pretty text-gray-950"> <p className="mt-2 max-w-2xl text-3xl lg:text-4xl font-medium tracking-tight text-pretty text-gray-950">
Network Capabilities Network Capabilities
</p> </p>
<p className="mt-4 max-w-xl text-lg text-gray-600"> <p className="mt-4 max-w-4xl text-lg text-gray-600">
Built for resilience and autonomy, the Mycelium Network dynamically connects nodes through intelligent routing, proxy discovery, and decentralized delivery. Built for resilience and autonomy, the Mycelium Network dynamically connects nodes through intelligent routing, proxy discovery, and decentralized delivery.
</p> </p>
<p className="mt-2 max-w-xl text-lg text-gray-600"> <p className="mt-2 max-w-4xl text-lg text-gray-600">
Each component from message passing to content distribution works in harmony to create a fully self-healing, self-optimizing data mesh. Each component from message passing to content distribution works in harmony to create a fully self-healing, self-optimizing data mesh.
</p> </p>
<div className="mt-10 grid grid-cols-1 gap-x-4 gap-y-8 sm:mt-16 lg:grid-cols-6 lg:grid-rows-2"> <div className="mt-10 grid grid-cols-1 gap-x-4 gap-y-8 sm:mt-16 lg:grid-cols-6 lg:grid-rows-2">
<div className="relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105"> <div className="group relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-t-4xl lg:rounded-tl-4xl" /> <div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-t-4xl lg:rounded-tl-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]"> <div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]">
<Pathfinding /> <Pathfinding />
@@ -34,9 +34,9 @@ Each component — from message passing to content distribution — works in har
</p> </p>
</div> </div>
</div> </div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-t-4xl lg:rounded-tl-4xl" /> <div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-t-4xl lg:rounded-tl-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div> </div>
<div className="relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105"> <div className="group relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-tr-4xl" /> <div className="absolute inset-0 rounded-lg bg-white lg:rounded-tr-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-tr-[calc(2rem+1px)]"> <div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-tr-[calc(2rem+1px)]">
<MessageBus /> <MessageBus />
@@ -51,9 +51,9 @@ Each component — from message passing to content distribution — works in har
</p> </p>
</div> </div>
</div> </div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-tr-4xl" /> <div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-tr-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div> </div>
<div className="relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105"> <div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-bl-4xl" /> <div className="absolute inset-0 rounded-lg bg-white lg:rounded-bl-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-bl-[calc(2rem+1px)]"> <div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-bl-[calc(2rem+1px)]">
<ProxyDetection className="h-80" /> <ProxyDetection className="h-80" />
@@ -68,9 +68,9 @@ Each component — from message passing to content distribution — works in har
</p> </p>
</div> </div>
</div> </div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-bl-4xl" /> <div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-bl-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div> </div>
<div className="relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105"> <div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white" /> <div className="absolute inset-0 rounded-lg bg-white" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)]"> <div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)]">
<ProxyForwarding className="h-80" /> <ProxyForwarding className="h-80" />
@@ -85,9 +85,9 @@ Each component — from message passing to content distribution — works in har
</p> </p>
</div> </div>
</div> </div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5" /> <div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div> </div>
<div className="relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105"> <div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-b-4xl lg:rounded-br-4xl" /> <div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-b-4xl lg:rounded-br-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]"> <div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]">
<ContentDistribution className="h-80" /> <ContentDistribution className="h-80" />
@@ -102,7 +102,7 @@ Each component — from message passing to content distribution — works in har
</p> </p>
</div> </div>
</div> </div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-br-4xl" /> <div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-br-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -255,7 +255,12 @@ function FeaturesDesktop() {
{features.map((feature, featureIndex) => ( {features.map((feature, featureIndex) => (
<div <div
key={feature.name} key={feature.name}
className="relative rounded-2xl transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30" className={clsx(
'relative rounded-2xl border transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30',
selectedIndex === featureIndex
? 'border-cyan-500'
: 'border-transparent hover:border-cyan-500',
)}
> >
{featureIndex === selectedIndex && ( {featureIndex === selectedIndex && (
<motion.div <motion.div
@@ -355,7 +360,14 @@ function FeaturesMobile() {
ref={(ref) => ref && (slideRefs.current[featureIndex] = ref)} ref={(ref) => 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" className="w-full flex-none snap-center px-4 sm:px-6 transition-all duration-300 ease-in-out hover:scale-105"
> >
<div className="relative transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6"> <div
className={clsx(
'relative transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6 border transition-colors',
activeIndex === featureIndex
? 'border-cyan-500'
: 'border-transparent hover:border-cyan-500',
)}
>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"> <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<CircleBackground <CircleBackground
color="#13B5C8" color="#13B5C8"

View File

@@ -210,7 +210,7 @@ export function SecondaryFeatures() {
{features.map((feature) => ( {features.map((feature) => (
<li <li
key={feature.name} key={feature.name}
className="rounded-2xl border border-gray-200 p-8 transition-all duration-300 ease-in-out hover:scale-105" className="rounded-2xl border border-gray-200 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
> >
<feature.icon className="h-8 w-8" /> <feature.icon className="h-8 w-8" />
<h3 className="mt-6 font-semibold text-gray-900"> <h3 className="mt-6 font-semibold text-gray-900">

View File

@@ -8,7 +8,7 @@ export function WindowsLink({
}) { }) {
return ( return (
<Link <Link
href="#" href="https://github.com/threefoldtech/myceliumflut/releases"
aria-label="Download for Windows" aria-label="Download for Windows"
className={clsx( className={clsx(
'flex items-center rounded-lg transition-colors px-4 py-2', 'flex items-center rounded-lg transition-colors px-4 py-2',