mirror of
https://github.com/Such-Software/such.software.git
synced 2026-10-18 05:41:26 +02:00
Splash: remove non-composited glow rings (fix mobile NO_LCP); cross-fade to content; nudge tracer target
- Drop the two animated glow rings: stroke-dashoffset is non-composited, so they repainted every frame next to the logo and prevented Lighthouse from settling on an LCP (mobile NO_LCP). The static box + pulsing glow remain. - Splash now cross-fades into the content: on enter it becomes a fixed overlay and fades opacity to 0 over the revealed page, instead of a hard cut. - Nebula tracer target moved up-and-left (computerX-1, computerY-1.5) so the streamers converge on the monitor screen, not below-right of it. - Removed the now-unused splash-* keyframes.
This commit is contained in:
@@ -227,16 +227,4 @@
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Splash hero idle animations as CSS (browser/compositor driven) instead of
|
||||
framer-motion, so they cost no JS main-thread time. The reduced-motion block
|
||||
above neutralizes them. */
|
||||
@keyframes splash-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
|
||||
@keyframes splash-breath { 0%, 100% { opacity: 0.9; } 50% { opacity: 1; } }
|
||||
@keyframes splash-ring-a { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -1; } }
|
||||
@keyframes splash-ring-b { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 1; } }
|
||||
.splash-float { animation: splash-float 6s ease-in-out infinite; }
|
||||
.splash-breath { animation: splash-breath 5s ease-in-out infinite; }
|
||||
.splash-ring-a { animation: splash-ring-a 5s linear infinite; }
|
||||
.splash-ring-b { animation: splash-ring-b 7s linear infinite; }
|
||||
}
|
||||
@@ -22,6 +22,10 @@ export default function Home() {
|
||||
// header, bottom nav, and background take over. Scrolling back up lands on the hero,
|
||||
// never the splash again.
|
||||
const [entered, setEntered] = useState(false);
|
||||
// `splashUp` keeps the splash mounted through its fade-out; `leaving` triggers the
|
||||
// cross-fade overlay (button path only).
|
||||
const [splashUp, setSplashUp] = useState(true);
|
||||
const [leaving, setLeaving] = useState(false);
|
||||
const splashRef = useRef<HTMLElement>(null);
|
||||
const restoreScroll = useRef(0);
|
||||
|
||||
@@ -31,6 +35,7 @@ export default function Home() {
|
||||
useIsoLayoutEffect(() => {
|
||||
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
||||
setEntered(true);
|
||||
setSplashUp(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -49,6 +54,7 @@ export default function Home() {
|
||||
if (!entry.isIntersecting) {
|
||||
restoreScroll.current = Math.max(0, window.scrollY - el.offsetHeight);
|
||||
setEntered(true);
|
||||
setSplashUp(false); // scrolled past: just unmount, no overlay fade needed
|
||||
}
|
||||
},
|
||||
{ threshold: 0 },
|
||||
@@ -85,6 +91,10 @@ export default function Home() {
|
||||
const enterFromButton = () => {
|
||||
restoreScroll.current = 0;
|
||||
setEntered(true);
|
||||
setLeaving(true);
|
||||
// Keep the splash mounted briefly as a fixed, fading overlay so it cross-fades
|
||||
// into the revealed content instead of hard-cutting.
|
||||
setTimeout(() => setSplashUp(false), 800);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -92,7 +102,7 @@ export default function Home() {
|
||||
<DynamicBackground nebulaPosition={nebulaPosition} visible={entered} />
|
||||
<Header floating visible={entered} />
|
||||
|
||||
{!entered && <HeroSplash sectionRef={splashRef} onEnter={enterFromButton} />}
|
||||
{splashUp && <HeroSplash sectionRef={splashRef} onEnter={enterFromButton} leaving={leaving} />}
|
||||
|
||||
<div id="main-content" className="z-10 w-full max-w-7xl mx-auto flex flex-col items-center pt-32 pb-10 px-4 text-center scroll-mt-28">
|
||||
<h1
|
||||
|
||||
Reference in New Issue
Block a user