From 01888d0b65876e4dec2765184987fbf1d63006fd Mon Sep 17 00:00:00 2001 From: James Kenneth Guidaven Date: Fri, 31 Jan 2025 16:53:36 +0800 Subject: [PATCH] A4A: Add swipe gesture on the carousel component. (#99039) * Add swipe gesture on the carousel component. * Make the carousel swift gesture more immediate. * Make the carousel feels like you are dragging the menu when swiping. * Make it feel like the carousel snaps when swiping at certain threshold. --- .../components/a4a-carousel/index.tsx | 42 ++++++++++++++++++- .../components/a4a-carousel/style.scss | 4 ++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/client/a8c-for-agencies/components/a4a-carousel/index.tsx b/client/a8c-for-agencies/components/a4a-carousel/index.tsx index 5b1f613a4049e..77a413e7c1545 100644 --- a/client/a8c-for-agencies/components/a4a-carousel/index.tsx +++ b/client/a8c-for-agencies/components/a4a-carousel/index.tsx @@ -12,6 +12,7 @@ type Props = { export default function A4ACarousel( { children, className }: Props ) { const [ offsetX, setOffsetX ] = useState( 0 ); + const [ touchStart, setTouchStart ] = useState< number | null >( null ); const contentRef = useRef< HTMLDivElement >( null ); const containerRef = useRef< HTMLDivElement >( null ); @@ -31,9 +32,48 @@ export default function A4ACarousel( { children, className }: Props ) { setOffsetX( Math.max( offsetX - offsetStep, -maxOffset ) ); }, [ offsetX, offsetStep, maxOffset ] ); + const onTouchStart = ( e: React.TouchEvent ) => { + setTouchStart( e.targetTouches[ 0 ].clientX ); + }; + + const onTouchMove = ( e: React.TouchEvent ) => { + if ( ! touchStart ) { + return; + } + + const currentTouch = e.targetTouches[ 0 ].clientX; + const distance = touchStart - currentTouch; + + // If distance is greater than threshold, snap to next/previous + const snapThreshold = containerWidth * 0.2; // 20% of container width + if ( Math.abs( distance ) > snapThreshold ) { + const newOffset = + distance > 0 + ? Math.max( offsetX - offsetStep, -maxOffset ) + : Math.min( offsetX + offsetStep, 0 ); + setOffsetX( newOffset ); + } else { + // Otherwise do smooth tracking + const newOffset = Math.max( Math.min( offsetX - distance, 0 ), -maxOffset ); + setOffsetX( newOffset ); + } + + setTouchStart( currentTouch ); + }; + + const onTouchEnd = () => { + setTouchStart( null ); + }; + return (
-
+