From 7d06c7ae18a94d98e12ccf3f212f98a8afc0433a Mon Sep 17 00:00:00 2001 From: Tanvi Bhatt Date: Sat, 11 Jul 2026 23:57:30 +0530 Subject: [PATCH] feat: add infinite scrolling animation to testimonials section --- frontend/src/LandingPage.jsx | 189 ++++++----------------------------- frontend/src/index.css | 18 ++++ 2 files changed, 47 insertions(+), 160 deletions(-) diff --git a/frontend/src/LandingPage.jsx b/frontend/src/LandingPage.jsx index 540904e..2c2dadc 100644 --- a/frontend/src/LandingPage.jsx +++ b/frontend/src/LandingPage.jsx @@ -990,8 +990,6 @@ const LandingPage = () => { const [activeStep, setActiveStep] = useState(1); const [showScrollTop, setShowScrollTop] = useState(false); - const [visibleCards, setVisibleCards] = useState(3); - const [currentIndex, setCurrentIndex] = useState(0); const [isPaused, setIsPaused] = useState(false); // Hero parallax @@ -1017,56 +1015,6 @@ const LandingPage = () => { statsRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }); }; - useEffect(() => { - const handleResize = () => { - if (window.innerWidth < 640) { - setVisibleCards(1); - } else if (window.innerWidth < 1024) { - setVisibleCards(2); - } else { - setVisibleCards(3); - } - }; - handleResize(); - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); - - useEffect(() => { - const maxIndex = Math.max(0, TESTIMONIALS.length - visibleCards); - if (currentIndex > maxIndex) { - setCurrentIndex(maxIndex); - } - }, [visibleCards, currentIndex]); - - useEffect(() => { - if (isPaused) return; - const interval = setInterval(() => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex + 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex > maxIndex ? 0 : nextIndex; - }); - }, 4000); - return () => clearInterval(interval); - }, [visibleCards, isPaused]); - - const handlePrev = () => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex - 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex < 0 ? maxIndex : nextIndex; - }); - }; - - const handleNext = () => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex + 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex > maxIndex ? 0 : nextIndex; - }); - }; - const handleCTA = () => { if (!user) { setOpenAuthModal(true); @@ -1601,114 +1549,35 @@ const LandingPage = () => { {/* ───────────────────────────────── TESTIMONIALS – auto-scrolling carousel ───────────────────────────────── */} -
-
- - - What Our Users Say - -

- Trusted by{" "} - - Thousands of Developers - -

-
- - {/* Testimonials Scroller */} -
setIsPaused(true)} - onMouseLeave={() => setIsPaused(false)} - > - {/* Fading overlays */} -
-
- - {/* Slider Track Wrapper */} -
-
- {TESTIMONIALS.map((testimonial) => ( -
- -
- ))} -
-
- - {/* Navigation Arrows and Dot Indicators */} -
- - - {/* Dots indicators */} -
- {Array.from({ length: TESTIMONIALS.length - visibleCards + 1 }).map((_, idx) => ( -
- - -
-
-
-
- - {/* ───────────────────────────────── - CTA FOOTER BANNER - ───────────────────────────────── */} -
-
-
-
- -

- Ready to Ace Your{" "} - - Next Interview? - -

-

- Join thousands of learners who have transformed their interview - preparation with PrepPilot AI. -

- -
-
+ {/* Testimonials Scroller */} +
setIsPaused(true)} + onMouseLeave={() => setIsPaused(false)} +> + {/* Left Fade */} +
+ + {/* Right Fade */} +
+ +
+
+ {[...TESTIMONIALS, ...TESTIMONIALS].map((testimonial, index) => ( +
+ +
+ ))} +
+
+
{/* ───────────────────────────────── FOOTER diff --git a/frontend/src/index.css b/frontend/src/index.css index 2c35d10..393bbb7 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -385,3 +385,21 @@ html.dark { } } +/* Infinite Testimonials */ + +@keyframes marquee { + from { + transform: translateX(0%); + } + to { + transform: translateX(-50%); + } +} + +.animate-marquee { + animation: marquee 30s linear infinite; +} + +.animate-marquee.paused { + animation-play-state: paused; +} \ No newline at end of file