diff --git a/client/src/components/netflix-grid.tsx b/client/src/components/netflix-grid.tsx index 00e4445..2472570 100644 --- a/client/src/components/netflix-grid.tsx +++ b/client/src/components/netflix-grid.tsx @@ -136,38 +136,22 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { const scrollIntervalRef = useRef(null); const [showLeftButton, setShowLeftButton] = useState(false); const [showRightButton, setShowRightButton] = useState(true); + + // Create infinite carousel by duplicating videos + const infiniteVideos = [...category.videos, ...category.videos, ...category.videos]; const scroll = (direction: 'left' | 'right') => { if (!scrollRef.current) return; const container = scrollRef.current; - const currentScroll = container.scrollLeft; - const maxScroll = container.scrollWidth - container.clientWidth; const videoWidth = 224; // approx width of one video card + spacing - const scrollAmount = videoWidth * 3; // Show 3 videos at a time - - let targetScroll; + const scrollAmount = videoWidth * 2; // Show 2 videos at a time if (direction === 'left') { - if (currentScroll <= 10) { - // Jump to end for infinite loop - targetScroll = maxScroll; - } else { - targetScroll = currentScroll - scrollAmount; - } + container.scrollBy({ left: -scrollAmount, behavior: 'smooth' }); } else { - if (currentScroll >= maxScroll - 10) { - // Jump to beginning for infinite loop - targetScroll = 0; - } else { - targetScroll = currentScroll + scrollAmount; - } + container.scrollBy({ left: scrollAmount, behavior: 'smooth' }); } - - container.scrollTo({ - left: targetScroll, - behavior: 'smooth' - }); }; const startAutoScroll = (direction: 'left' | 'right') => { @@ -176,14 +160,36 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { }; const checkScrollPosition = () => { - // Always show both buttons for infinite carousel + if (!scrollRef.current) return; + + const container = scrollRef.current; + const currentScroll = container.scrollLeft; + const maxScroll = container.scrollWidth - container.clientWidth; + const sectionWidth = (container.scrollWidth / 3); // One third (original videos) + + // Reset to middle section when approaching edges for infinite effect + if (currentScroll <= 100) { + // Jump to end of first section (start of second section) + container.scrollLeft = sectionWidth + currentScroll; + } else if (currentScroll >= maxScroll - 100) { + // Jump to start of second section + container.scrollLeft = sectionWidth + (currentScroll - 2 * sectionWidth); + } + + // Always show both buttons setShowLeftButton(true); setShowRightButton(true); }; - // Check scroll position on mount and when videos change + // Initialize position to middle section on mount useEffect(() => { - checkScrollPosition(); + if (scrollRef.current && category.videos.length > 0) { + const container = scrollRef.current; + const sectionWidth = container.scrollWidth / 3; + container.scrollLeft = sectionWidth; // Start in middle section + setShowLeftButton(true); + setShowRightButton(true); + } }, [category.videos]); const stopAutoScroll = () => { @@ -290,8 +296,8 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) { WebkitOverflowScrolling: 'touch' }} > - {category.videos.map((video, index) => ( -
+ {infiniteVideos.map((video, index) => ( +
{/* Top 10 Number overlay for first category */} {category.title.includes("Top 10") && index < 10 && (