import { useState, useEffect, useRef } from 'react'; interface LazyImageProps { src: string; alt: string; className?: string; width?: number; height?: number; placeholder?: string; } /** * Lazy-loaded image component with intersection observer * Only loads images when they're about to enter the viewport */ export function LazyImage({ src, alt, className = '', width, height, placeholder = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300"%3E%3Crect fill="%23e5e7eb" width="400" height="300"/%3E%3C/svg%3E' }: LazyImageProps) { const [imageSrc, setImageSrc] = useState(placeholder); const [isLoaded, setIsLoaded] = useState(false); const imgRef = useRef(null); useEffect(() => { // Check if IntersectionObserver is supported if (!('IntersectionObserver' in window)) { // Fallback: load image immediately setImageSrc(src); return; } const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { setImageSrc(src); if (imgRef.current) { observer.unobserve(imgRef.current); } } }); }, { rootMargin: '50px', // Start loading 50px before entering viewport } ); if (imgRef.current) { observer.observe(imgRef.current); } return () => { if (imgRef.current) { observer.unobserve(imgRef.current); } }; }, [src]); return ( {alt} setIsLoaded(true)} /> ); } export default LazyImage;