From facca114e0c017615ead81590774d43a244bbcda Mon Sep 17 00:00:00 2001 From: Harsh Jain <121497446+Harsh8089@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:27:37 +0530 Subject: [PATCH] Added drag-to-scroll functionality for Testimonials section (#533) --- src/components/ui/infinite-moving-cards.tsx | 72 +++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/components/ui/infinite-moving-cards.tsx b/src/components/ui/infinite-moving-cards.tsx index b1702a80..7093d8bb 100644 --- a/src/components/ui/infinite-moving-cards.tsx +++ b/src/components/ui/infinite-moving-cards.tsx @@ -20,9 +20,78 @@ export const InfiniteMovingCards = ({ const containerRef = React.useRef(null); const scrollerRef = React.useRef(null); + const [isDown, setIsDown] = useState(false); + const [startX, setStartX] = useState(0.0); + const [scrollLeft, setscrollLeft] = useState(0.0); + const [totalWidth, setTotalWidth] = useState(0.0); + + useEffect(() => { + const slider = containerRef.current; + const handleMouseDown = (event: MouseEvent) => { + if (!slider) return; + setIsDown(true); + setStartX(event.pageX - slider.offsetLeft); + setscrollLeft(slider.scrollLeft); + }; + + const handleMouseMove = (event: MouseEvent) => { + if (slider && isDown) { + const x = event.pageX - slider.offsetLeft; + const walk = x - startX; + const newScrollLeft = scrollLeft - walk; + + const maxScrollLeft = totalWidth - slider.clientWidth; + + if (newScrollLeft < 0) slider.scrollLeft = 0; + else if (newScrollLeft > maxScrollLeft) + slider.scrollLeft = maxScrollLeft; + else slider.scrollLeft = newScrollLeft; + } + }; + + const handleMouseLeave = () => { + setIsDown(false); + }; + + const handleMouseUp = () => { + setIsDown(false); + }; + + if (slider) { + slider.addEventListener('mousedown', handleMouseDown); + slider.addEventListener('mousemove', handleMouseMove); + slider.addEventListener('mouseleave', handleMouseLeave); + slider.addEventListener('mouseup', handleMouseUp); + } + + return () => { + if (slider) { + slider.removeEventListener('mousedown', handleMouseDown); + slider.removeEventListener('mousemove', handleMouseMove); + slider.removeEventListener('mouseleave', handleMouseLeave); + slider.removeEventListener('mouseup', handleMouseMove); + } + }; + }, [isDown, startX, scrollLeft]); + useEffect(() => { addAnimation(); + const scroller = scrollerRef.current; + if (scroller) { + const listItems = scroller.querySelectorAll('li'); + let width = 0, + length = 0; + listItems.forEach((item) => { + if (length < listItems.length / 2) + width += + (item as HTMLElement).offsetWidth + + parseFloat(getComputedStyle(item).marginRight); + length++; + }); + setTotalWidth(width); + } }, []); + const [start, setStart] = useState(false); function addAnimation() { if (containerRef.current && scrollerRef.current) { @@ -64,6 +133,9 @@ export const InfiniteMovingCards = ({ 'scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]', className )} + style={{ + userSelect: 'none', + }} >