From 1ff31b5d08981558d8955c9411be3f0ed0d9ad2a Mon Sep 17 00:00:00 2001 From: kudinDmitriyUp Date: Sun, 14 Jun 2026 04:04:08 +0000 Subject: [PATCH] Bob AI: add an interaction layer to the testimonial carousel where i --- src/pages/HomePage/sections/Testimonials.tsx | 74 ++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/pages/HomePage/sections/Testimonials.tsx b/src/pages/HomePage/sections/Testimonials.tsx index c54021c..d5f91f5 100644 --- a/src/pages/HomePage/sections/Testimonials.tsx +++ b/src/pages/HomePage/sections/Testimonials.tsx @@ -5,6 +5,80 @@ import TextAnimation from "@/components/ui/TextAnimation"; import ImageOrVideo from "@/components/ui/ImageOrVideo"; import ScrollReveal from "@/components/ui/ScrollReveal"; import { BadgeCheck } from "lucide-react"; +import { useRef, useState } from "react"; + +const DraggableMarqueeRow = ({ items, duration, reverse = false }: { items: any[], duration: string, reverse?: boolean }) => { + const containerRef = useRef(null); + const [isHovered, setIsHovered] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const [startX, setStartX] = useState(0); + const [scrollLeft, setScrollLeft] = useState(0); + + const handleMouseDown = (e: React.MouseEvent) => { + if (!containerRef.current) return; + setIsDragging(true); + setStartX(e.pageX - (containerRef.current as any).offsetLeft); + setScrollLeft((containerRef.current as any).scrollLeft); + }; + + const handleMouseLeave = () => { + setIsDragging(false); + setIsHovered(false); + }; + + const handleMouseUp = () => { + setIsDragging(false); + }; + + const handleMouseMove = (e: React.MouseEvent) => { + if (!isDragging || !containerRef.current) return; + e.preventDefault(); + const x = e.pageX - (containerRef.current as any).offsetLeft; + const walk = (x - startX) * 2; + (containerRef.current as any).scrollLeft = scrollLeft - walk; + }; + + return ( +
setIsHovered(true)} + onMouseLeave={handleMouseLeave} + onMouseDown={handleMouseDown} + onMouseUp={handleMouseUp} + onMouseMove={handleMouseMove} + style={{ overflowX: isHovered ? 'auto' : 'hidden', scrollbarWidth: 'none', msOverflowStyle: 'none' }} + > +
+ {[...items, ...items, ...items, ...items].map((item, i) => ( +
+
+
+

"{item.quote}"

+
+
+
+ +
+
+
+

{item.name}

+ +
+

{item.role}

+
+
+
+
+ ))} +
+
+ ); +}; const testimonials = [ { -- 2.49.1