From 6cc5e038a76276f3ff12eabb7a3159029150af93 Mon Sep 17 00:00:00 2001 From: geoffsee <> Date: Tue, 1 Jul 2025 15:43:17 -0400 Subject: [PATCH] Add `visible` prop to toggle components and simplify conditional rendering --- .../landing-component/BevyScene.tsx | 72 +++++++++---------- .../landing-component/LandingComponent.tsx | 10 +-- .../landing-component/MatrixRain.tsx | 11 ++- .../landing-component/Particles.tsx | 13 ++-- 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/packages/client/src/components/landing-component/BevyScene.tsx b/packages/client/src/components/landing-component/BevyScene.tsx index 3898fc9..de5143f 100644 --- a/packages/client/src/components/landing-component/BevyScene.tsx +++ b/packages/client/src/components/landing-component/BevyScene.tsx @@ -1,51 +1,51 @@ import { Box } from '@chakra-ui/react'; -import { useEffect } from 'react'; +import React, { memo, useEffect, useMemo } from 'react'; export interface BevySceneProps { - speed?: number; // transition seconds - intensity?: number; + speed?: number; + intensity?: number; // 0-1 when visible glow?: boolean; + visible?: boolean; // NEW — defaults to true } -export const BevyScene: React.FC = ({ speed = 1, intensity = 1, glow = false }) => { +const BevySceneInner: React.FC = ({ + speed = 1, + intensity = 1, + glow = false, + visible, +}) => { + /* initialise once */ useEffect(() => { + let dispose: (() => void) | void; (async () => { - const module = await import('/public/yachtpit.js', { type: 'module' }); - console.log('init', module); - await module.default(); + const { default: init } = await import(/* webpackIgnore: true */ '/public/yachtpit.js'); + dispose = await init(); // zero-arg, uses #yachtpit-canvas })(); - // const script = document.createElement('script'); - // script.src = ''; - // script.type = 'module'; - // document.body.appendChild(script); - // script.onload = loaded => { - // loaded.target?.init(); - // console.log('loaded', loaded); - // }; + return () => { + if (typeof dispose === 'function') dispose(); + }; }, []); + /* memoised styles */ + const wrapperStyles = useMemo( + () => ({ + position: 'absolute' as const, + inset: 0, + zIndex: 0, + pointerEvents: 'none' as const, + opacity: visible ? Math.min(Math.max(intensity, 0), 1) : 0, + filter: glow ? 'blur(1px)' : 'none', + transition: `opacity ${speed}s ease-in-out`, + display: visible ? 'block' : 'none', // optional: reclaim hit-testing entirely + }), + [visible, intensity, glow, speed], + ); + return ( - - - - {/**/} + + ); }; + +export const BevyScene = memo(BevySceneInner); diff --git a/packages/client/src/components/landing-component/LandingComponent.tsx b/packages/client/src/components/landing-component/LandingComponent.tsx index dc34a99..7d8b833 100644 --- a/packages/client/src/components/landing-component/LandingComponent.tsx +++ b/packages/client/src/components/landing-component/LandingComponent.tsx @@ -34,7 +34,7 @@ export const LandingComponent: React.FC = () => { { ariaLabel: 'animation-speed', }, intensity: { - value: intensity, + value: !particles ? intensity : 0.99, onChange: setIntensity, label: 'Effect Intensity', min: 0.01, @@ -94,9 +94,9 @@ export const LandingComponent: React.FC = () => { }} /> - {!particles && !matrixRain && } - {!particles && matrixRain && } - {particles && } + + + ); }; diff --git a/packages/client/src/components/landing-component/MatrixRain.tsx b/packages/client/src/components/landing-component/MatrixRain.tsx index cbeff94..c7a5a55 100644 --- a/packages/client/src/components/landing-component/MatrixRain.tsx +++ b/packages/client/src/components/landing-component/MatrixRain.tsx @@ -8,12 +8,14 @@ interface MatrixRainProps { speed?: number; glow?: boolean; intensity?: number; + visible?: boolean; } export const MatrixRain: React.FC = ({ speed = 1, glow = false, intensity = 1, + visible, }) => { const fontSize = useBreakpointValue({ base: 14, md: 18, lg: 22 }) ?? 14; const theme = useTheme(); @@ -111,7 +113,12 @@ export const MatrixRain: React.FC = ({ cancelAnimationFrame(animationRef.current); } }; - }, [fontSize, speed, glow, intensity]); + }, [fontSize, speed, glow, intensity, visible]); - return ; + return ( + + ); }; diff --git a/packages/client/src/components/landing-component/Particles.tsx b/packages/client/src/components/landing-component/Particles.tsx index 619f5e0..83ec36d 100644 --- a/packages/client/src/components/landing-component/Particles.tsx +++ b/packages/client/src/components/landing-component/Particles.tsx @@ -6,6 +6,7 @@ interface ParticlesProps { intensity: number; particles: boolean; glow: boolean; + visible?: boolean; } interface Particle { @@ -16,7 +17,7 @@ interface Particle { size: number; } -const Particles: React.FC = ({ speed, intensity, particles, glow }) => { +const Particles: React.FC = ({ speed, intensity, glow, visible }) => { const canvasRef = useRef(null); const particlesRef = useRef([]); const animationFrameRef = useRef(undefined); @@ -33,7 +34,7 @@ const Particles: React.FC = ({ speed, intensity, particles, glow // Main animation effect useEffect(() => { - if (!particles) { + if (!visible) { if (animationFrameRef.current) { cancelAnimationFrame(animationFrameRef.current); animationFrameRef.current = undefined; @@ -128,11 +129,11 @@ const Particles: React.FC = ({ speed, intensity, particles, glow animationFrameRef.current = undefined; } }; - }, [particles, intensity, speed, glow, theme.colors.text.accent]); + }, [visible, intensity, speed, glow, theme.colors.text.accent]); // Separate effect for speed changes - update existing particle velocities useEffect(() => { - if (!particles) return; + if (!visible) return; particlesRef.current.forEach(particle => { const currentSpeed = Math.sqrt(particle.vx * particle.vx + particle.vy * particle.vy); @@ -146,13 +147,13 @@ const Particles: React.FC = ({ speed, intensity, particles, glow particle.vy = (Math.random() - 0.5) * speed; } }); - }, [speed, particles]); + }, [speed, visible]); return ( );