šProblem Statement
Build an image carousel like Instagram stories or product galleries.
šRequirements
šCore Implementation
const Carousel = ({ images, autoPlay = false, interval = 3000 }) => { const [currentIndex, setCurrentIndex] = useState(0); const [isPlaying, setIsPlaying] = useState(autoPlay); const touchStartX = useRef(0); const touchEndX = useRef(0); useEffect(() => { if (!isPlaying) return; const timer = setInterval(() => { setCurrentIndex(prev => (prev + 1) % images.length); }, interval); return () => clearInterval(timer); }, [isPlaying, images.length, interval]); const goTo = (index) => { setCurrentIndex(index); setIsPlaying(false); }; const next = () => goTo((currentIndex + 1) % images.length); const prev = () => goTo((currentIndex - 1 + images.length) % images.length); const handleTouchStart = (e) => { touchStartX.current = e.touches[0].clientX; }; const handleTouchEnd = (e) => { touchEndX.current = e.changedTouches[0].clientX; const diff = touchStartX.current - touchEndX.current; if (Math.abs(diff) > 50) { diff > 0 ? next() : prev(); } }; return ( <div className="carousel" onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onKeyDown={handleKeyDown} tabIndex={0} > <div className="carousel-track" style={{ transform: `translateX(-${currentIndex * 100}%)` }} > {images.map((img, index) => ( <img key={index} src={img.src} alt={img.alt} loading={Math.abs(index - currentIndex) <= 1 ? 'eager' : 'lazy'} /> ))} </div> <button onClick={prev} className="carousel-btn prev">ā¹</button> <button onClick={next} className="carousel-btn next">āŗ</button> <div className="carousel-dots"> {images.map((_, index) => ( <button key={index} onClick={() => goTo(index)} className={`dot ${index === currentIndex ? 'active' : ''}`} /> ))} </div> </div> );};šCSS for Smooth Transitions
.carousel { position: relative; overflow: hidden;}.carousel-track { display: flex; transition: transform 0.3s ease-out;}.carousel-track img { flex-shrink: 0; width: 100%; object-fit: cover;}šKeyboard Navigation
const handleKeyDown = (e) => { switch (e.key) { case 'ArrowLeft': prev(); break; case 'ArrowRight': next(); break; case ' ': e.preventDefault(); setIsPlaying(prev => !prev); break; }};šAccessibility
role="region" with aria-labelaria-live="polite" for announcementsAsked at Amazon, Flipkart, and e-commerce companies.