From d5bb6eb12a3de7ee8c16dcc24c97186e0c1367d5 Mon Sep 17 00:00:00 2001 From: Nancy Verma Date: Fri, 29 May 2026 15:06:21 +0530 Subject: [PATCH 1/2] Implement infinite scroll for learning paths --- src/components/home/LearningPaths.tsx | 36 ++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/home/LearningPaths.tsx b/src/components/home/LearningPaths.tsx index 3ab3e924..c8bc084e 100644 --- a/src/components/home/LearningPaths.tsx +++ b/src/components/home/LearningPaths.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { Clock, BookOpen, ArrowRight, Bell } from 'lucide-react'; import Button from '../ui/Button'; import ComingSoonBadge from '../features/ComingSoonBadge'; @@ -65,6 +65,27 @@ export default function LearningPaths() { const [selectedPath, setSelectedPath] = useState(""); const [email, setEmail] = useState(""); const [isSubmitted, setIsSubmitted] = useState(false); + + // Infinite Scroll State Configuration Layer + const [visibleCount, setVisibleCount] = useState(2); + const observerAnchorRef = useRef(null); + + useEffect(() => { + const targetAnchor = observerAnchorRef.current; + if (!targetAnchor) return; + + const scrollObserver = new IntersectionObserver((intersectEntries) => { + if (intersectEntries[0].isIntersecting && visibleCount < paths.length) { + // Smoothly increment visible cards batching list + setVisibleCount((prevValue) => Math.min(prevValue + 2, paths.length)); + } + }, { threshold: 0.1 }); + + scrollObserver.observe(targetAnchor); + return () => { + if (targetAnchor) scrollObserver.unobserve(targetAnchor); + }; + }, [visibleCount]); const handlePathClick = (path: Path) => { if (path.status === 'coming-soon') { @@ -77,7 +98,6 @@ export default function LearningPaths() { const handleNotifySubmit = (e: React.FormEvent) => { e.preventDefault(); - // Simulate API call setTimeout(() => { setIsSubmitted(true); }, 1000); @@ -93,7 +113,7 @@ export default function LearningPaths() {
- {paths.map((path, index) => ( + {paths.slice(0, visibleCount).map((path, index) => (
+ {/* Core Infinite Scroll Interceptor Trigger Target Element */} +
+ {visibleCount < paths.length ? ( + 🔄 Loading more tracks... + ) : ( + 🎉 You have reached the end of the roadmaps! + )} +
+ {showNotifyModal && (
setShowNotifyModal(false)}>
e.stopPropagation()}> @@ -185,3 +214,4 @@ export default function LearningPaths() { ); } + From f38ebd74bfc342eb9fda189d4df07f11767b1b33 Mon Sep 17 00:00:00 2001 From: Nancy Verma Date: Fri, 29 May 2026 16:00:55 +0530 Subject: [PATCH 2/2] Update LearningPaths.tsx --- src/components/home/LearningPaths.tsx | 31 +++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/components/home/LearningPaths.tsx b/src/components/home/LearningPaths.tsx index c8bc084e..c5dfd254 100644 --- a/src/components/home/LearningPaths.tsx +++ b/src/components/home/LearningPaths.tsx @@ -66,7 +66,7 @@ export default function LearningPaths() { const [email, setEmail] = useState(""); const [isSubmitted, setIsSubmitted] = useState(false); - // Infinite Scroll State Configuration Layer + // Horizontal Infinite Scroll State Configuration const [visibleCount, setVisibleCount] = useState(2); const observerAnchorRef = useRef(null); @@ -76,10 +76,13 @@ export default function LearningPaths() { const scrollObserver = new IntersectionObserver((intersectEntries) => { if (intersectEntries[0].isIntersecting && visibleCount < paths.length) { - // Smoothly increment visible cards batching list - setVisibleCount((prevValue) => Math.min(prevValue + 2, paths.length)); + // Smoothly load next horizontal elements block + setVisibleCount((prevValue) => Math.min(prevValue + 1, paths.length)); } - }, { threshold: 0.1 }); + }, { + root: targetAnchor.parentElement, // Tracks scrolling within the carousel container box + threshold: 0.1 + }); scrollObserver.observe(targetAnchor); return () => { @@ -112,12 +115,12 @@ export default function LearningPaths() {

-
+
{paths.slice(0, visibleCount).map((path, index) => (
handlePathClick(path)} > {path.status === 'coming-soon' && } @@ -165,15 +168,15 @@ export default function LearningPaths() {
))} -
- {/* Core Infinite Scroll Interceptor Trigger Target Element */} -
- {visibleCount < paths.length ? ( - 🔄 Loading more tracks... - ) : ( - 🎉 You have reached the end of the roadmaps! - )} + {/* Horizontal Interceptor Trigger Target Element (placed at the right end inside the slider container) */} +
+ {visibleCount < paths.length ? ( + 🔄 + ) : ( + 🎉 + )} +
{showNotifyModal && (