import { useEffect, useRef } from 'react' import { useReducedMotion } from '../hooks/useReducedMotion' interface Particle { x: number y: number size: number speedX: number speedY: number opacity: number color: string } export default function FloatingParticles() { const canvasRef = useRef(null) const reducedMotion = useReducedMotion() useEffect(() => { if (reducedMotion) return const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') if (!ctx) return let animationId: number let particles: Particle[] = [] const resize = () => { canvas.width = window.innerWidth canvas.height = window.innerHeight } resize() window.addEventListener('resize', resize) const colors = ['rgba(255, 45, 122, 0.15)', 'rgba(255, 107, 157, 0.12)', 'rgba(255, 182, 193, 0.1)'] const createParticles = () => { particles = [] const count = Math.min(Math.floor(window.innerWidth / 15), 80) for (let i = 0; i < count; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, size: Math.random() * 3 + 1, speedX: (Math.random() - 0.5) * 0.3, speedY: (Math.random() - 0.5) * 0.3, opacity: Math.random() * 0.5 + 0.1, color: colors[Math.floor(Math.random() * colors.length)], }) } } createParticles() const animate = () => { ctx.clearRect(0, 0, canvas.width, canvas.height) particles.forEach((p) => { p.x += p.speedX p.y += p.speedY if (p.x < 0) p.x = canvas.width if (p.x > canvas.width) p.x = 0 if (p.y < 0) p.y = canvas.height if (p.y > canvas.height) p.y = 0 ctx.beginPath() ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2) ctx.fillStyle = p.color ctx.fill() }) animationId = requestAnimationFrame(animate) } animate() return () => { cancelAnimationFrame(animationId) window.removeEventListener('resize', resize) } }, [reducedMotion]) if (reducedMotion) return null return ( ) }