diff --git a/client/src/components/netflix-grid.tsx b/client/src/components/netflix-grid.tsx index 7edd4f8..7df2b4d 100644 --- a/client/src/components/netflix-grid.tsx +++ b/client/src/components/netflix-grid.tsx @@ -137,17 +137,14 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { const [showLeftButton, setShowLeftButton] = useState(false); const [showRightButton, setShowRightButton] = useState(true); - const [currentIndex, setCurrentIndex] = useState(0); + const [translateX, setTranslateX] = useState(0); + const [isScrolling, setIsScrolling] = useState(false); const videosToShow = 5; // Show 5 videos at a time + const videoWidth = 120; // Width + spacing const scroll = (direction: 'left' | 'right') => { - if (direction === 'right') { - // Always move forward in the circle - perpetual motion - setCurrentIndex(prev => prev + 1); - } else { - // For left arrow, also move forward but faster to create illusion of reverse - setCurrentIndex(prev => prev + 1); - } + const speed = direction === 'right' ? videoWidth : -videoWidth; + setTranslateX(prev => prev - speed); }; const startAutoScroll = (direction: 'left' | 'right') => { @@ -156,29 +153,41 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { clearInterval(scrollIntervalRef.current); } - // Both directions move forward - true perpetual motion carousel - scrollIntervalRef.current = setInterval(() => { - setCurrentIndex(prev => prev + 1); - }, direction === 'left' ? 600 : 800); // Left moves slightly faster for effect + setIsScrolling(true); + + // Continuous smooth flowing animation + const speed = direction === 'right' ? 2 : -2; // pixels per frame + + const animate = () => { + setTranslateX(prev => { + const newValue = prev - speed; + const totalWidth = category.videos.length * videoWidth; + + // Reset position for infinite loop + if (direction === 'right' && newValue <= -totalWidth) { + return 0; + } else if (direction === 'left' && newValue >= 0) { + return -totalWidth + videoWidth; + } + + return newValue; + }); + + if (isScrolling) { + scrollIntervalRef.current = requestAnimationFrame(animate); + } + }; + + animate(); }; - // Initialize in middle section for smooth infinite scroll + // Initialize starting position useEffect(() => { if (category.videos.length > 0) { - setCurrentIndex(category.videos.length); // Start in middle section for smooth wrapping + setTranslateX(-category.videos.length * videoWidth); // Start in middle section } }, [category.videos.length]); - // Handle seamless infinite scroll - only forward movement - useEffect(() => { - const totalVideos = category.videos.length; - if (currentIndex >= totalVideos * 2) { - // When we reach the end, seamlessly jump back to start of middle section - // This creates the illusion of infinite forward movement - setCurrentIndex(currentIndex - totalVideos); - } - }, [currentIndex, category.videos.length]); - // Always show both buttons useEffect(() => { setShowLeftButton(true); @@ -186,8 +195,9 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { }, []); const stopAutoScroll = () => { + setIsScrolling(false); if (scrollIntervalRef.current) { - clearInterval(scrollIntervalRef.current); + cancelAnimationFrame(scrollIntervalRef.current); scrollIntervalRef.current = null; } }; @@ -281,13 +291,14 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { - {/* Smooth sliding carousel - videos move like geese one by one */} + {/* Continuously flowing carousel - videos flow like water */}
{/* Create infinite loop by tripling the videos */}