forked from sashaastiadi/www_mycelium_net
style: update UI with darker background, remove animations and adjust layout spacing
This commit is contained in:
46
hooks/useScrollDirection.ts
Normal file
46
hooks/useScrollDirection.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
export type ScrollDirection = 'up' | 'down';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hook to detect the scroll direction.
|
||||||
|
* It uses requestAnimationFrame for performance, comparing the current scroll position
|
||||||
|
* with the previous one to determine if the user is scrolling up or down.
|
||||||
|
*
|
||||||
|
* @returns {ScrollDirection | null} The current scroll direction ('up' or 'down'), or null on the initial render.
|
||||||
|
*/
|
||||||
|
export function useScrollDirection(): ScrollDirection | null {
|
||||||
|
const [scrollDirection, setScrollDirection] = useState<ScrollDirection | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let lastScrollY = window.pageYOffset;
|
||||||
|
let ticking = false;
|
||||||
|
|
||||||
|
const updateScrollDirection = () => {
|
||||||
|
const scrollY = window.pageYOffset;
|
||||||
|
|
||||||
|
if (Math.abs(scrollY - lastScrollY) < 10) {
|
||||||
|
ticking = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setScrollDirection(scrollY > lastScrollY ? 'down' : 'up');
|
||||||
|
lastScrollY = scrollY > 0 ? scrollY : 0;
|
||||||
|
ticking = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onScroll = () => {
|
||||||
|
if (!ticking) {
|
||||||
|
window.requestAnimationFrame(updateScrollDirection);
|
||||||
|
ticking = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', onScroll);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('scroll', onScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return scrollDirection;
|
||||||
|
}
|
@@ -6,10 +6,10 @@ export function About() {
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id="about"
|
id="about"
|
||||||
className="relative overflow-hidden bg-gray-900 py-20 sm:py-28"
|
className="relative overflow-hidden bg-black py-20 sm:py-28"
|
||||||
>
|
>
|
||||||
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
|
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
|
||||||
<CircleBackground color="#fff" className="animate-spin-slower" />
|
<CircleBackground color="#fff" />
|
||||||
</div>
|
</div>
|
||||||
<Container className="relative">
|
<Container className="relative">
|
||||||
<div className="mx-auto max-w-3xl sm:text-center">
|
<div className="mx-auto max-w-3xl sm:text-center">
|
||||||
|
@@ -153,24 +153,31 @@ export default function ContentDistribution({ className, bg = '#ffffff' }: Props
|
|||||||
{/* central cloud */}
|
{/* central cloud */}
|
||||||
<Cloud />
|
<Cloud />
|
||||||
|
|
||||||
{/* rotating layer with badges */}
|
{/* rotating layer with badges and beams */}
|
||||||
<motion.g
|
<motion.g
|
||||||
initial={{ rotate: 0 }}
|
initial={{ rotate: 0 }}
|
||||||
animate={{ rotate: prefersReduced ? 0 : 360 }}
|
animate={{ rotate: prefersReduced ? 0 : 360 }}
|
||||||
transition={{ duration: 40, ease: 'linear', repeat: prefersReduced ? 0 : Infinity }}
|
transition={{ duration: 40, ease: 'linear', repeat: prefersReduced ? 0 : Infinity }}
|
||||||
>
|
>
|
||||||
|
{/* Beams */}
|
||||||
|
{layout.map((n, i) => {
|
||||||
|
const rad = (n.a * Math.PI) / 180;
|
||||||
|
const x = n.r * Math.cos(rad);
|
||||||
|
const y = n.r * Math.sin(rad);
|
||||||
|
return <Beam key={`beam-${i}`} x2={x} y2={y} delay={i * 0.15} />;
|
||||||
|
})}
|
||||||
|
|
||||||
|
{/* Badges */}
|
||||||
{layout.map((n, i) => {
|
{layout.map((n, i) => {
|
||||||
const rad = (n.a * Math.PI) / 180;
|
const rad = (n.a * Math.PI) / 180;
|
||||||
const x = n.r * Math.cos(rad);
|
const x = n.r * Math.cos(rad);
|
||||||
const y = n.r * Math.sin(rad);
|
const y = n.r * Math.sin(rad);
|
||||||
return (
|
return (
|
||||||
<g key={i} transform={`translate(${x}, ${y})`} filter="url(#shadow)">
|
<g key={`badge-${i}`} transform={`translate(${x}, ${y})`} filter="url(#shadow)">
|
||||||
<circle r={34} fill="#fff" stroke={GRAY_LT} strokeWidth={3} />
|
<circle r={34} fill="#fff" stroke={GRAY_LT} strokeWidth={3} />
|
||||||
<g transform="scale(1)">
|
<g transform="scale(1)">
|
||||||
{n.icon}
|
{n.icon}
|
||||||
</g>
|
</g>
|
||||||
{/* beam from center to this node (animated) */}
|
|
||||||
<Beam x2={-x} y2={-y} delay={i * 0.15} />
|
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@@ -8,7 +8,7 @@ export function LinuxLink({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href="#"
|
href="https://github.com/threefoldtech/mycelium/releases"
|
||||||
aria-label="Download for Linux"
|
aria-label="Download for Linux"
|
||||||
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',
|
||||||
|
@@ -410,7 +410,7 @@ function FeaturesDesktop() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TabGroup
|
<TabGroup
|
||||||
className="grid grid-cols-12 items-center gap-8 lg:gap-16 xl:gap-24"
|
className="grid grid-cols-12 items-center gap-8 lg:gap-16"
|
||||||
selectedIndex={selectedIndex}
|
selectedIndex={selectedIndex}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
vertical
|
vertical
|
||||||
|
Reference in New Issue
Block a user