From 4f0fa6adf6f28b57c6f29db26c2f63e93a29565a Mon Sep 17 00:00:00 2001 From: Kevin <83264008+coolestKev@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:29:20 -0500 Subject: [PATCH] task(HTL-113265): Pointer fix first commit (#1542) * task(HTL-113265): Pointer fix first commit * Rush change --- ...cate-two-pointer-fix_2024-12-20-15-44.json | 10 +++++ .../core/src/Drawer/hooks/useSnap.spec.ts | 24 +++++++---- packages/core/src/Drawer/hooks/useSnap.ts | 41 ++++++++++++++----- 3 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 common/changes/pcln-design-system/task-htl-113265-duplicate-two-pointer-fix_2024-12-20-15-44.json diff --git a/common/changes/pcln-design-system/task-htl-113265-duplicate-two-pointer-fix_2024-12-20-15-44.json b/common/changes/pcln-design-system/task-htl-113265-duplicate-two-pointer-fix_2024-12-20-15-44.json new file mode 100644 index 000000000..026708f16 --- /dev/null +++ b/common/changes/pcln-design-system/task-htl-113265-duplicate-two-pointer-fix_2024-12-20-15-44.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "pcln-design-system", + "comment": "Differentiate pointer type on scroll vs drag action", + "type": "patch" + } + ], + "packageName": "pcln-design-system" +} \ No newline at end of file diff --git a/packages/core/src/Drawer/hooks/useSnap.spec.ts b/packages/core/src/Drawer/hooks/useSnap.spec.ts index 3465b08db..1c30c6092 100644 --- a/packages/core/src/Drawer/hooks/useSnap.spec.ts +++ b/packages/core/src/Drawer/hooks/useSnap.spec.ts @@ -2,17 +2,27 @@ import { useSnap } from './useSnap' import { renderHook } from '@testing-library/react' describe('Drawer snap hook unit test', () => { + const snapHeights = ['20%', '0%', '20%'] + const snapDimensions = ['100%', '100%', '100%'] + const { result } = renderHook(() => useSnap(snapHeights, snapDimensions)) + const { snapPosition, handleSnap } = result.current test('Snap position initialized correctly', () => { - const { result } = renderHook(() => useSnap(['0%', '20%', '30%'], ['100%', '100%', '100%'])) - const { snapPosition, handleSnap } = result.current - expect(snapPosition).toBe('20%') - // Start middle, scroll up and scroll down should be back to initial position + expect(snapPosition).toBe('0%') // Scroll to top - handleSnap('', { offset: { y: 101 } }) + handleSnap({ pointerType: 'touch', type: 'pointerup' }, { offset: { y: 101 } }) // Scroll back to middle - handleSnap('', { offset: { y: -101 } }) + handleSnap({ pointerType: 'touch', type: 'pointerup' }, { offset: { y: -101 } }) + // Expect it to be back in middle + expect(snapPosition).toBe('0%') + }) - expect(snapPosition).toBe('20%') + test('Does not snap on pointer cancel events (e.g. scrolling through drawer content on iphone)', () => { + // Start middle, and touch scroll on drawer content should not trigger an action + expect(snapPosition).toBe('0%') + // Scroll to top + handleSnap({ pointerType: 'touch', type: 'pointercancel' }, { offset: { y: 101 } }) + // Expect no change + expect(snapPosition).toBe('0%') }) }) diff --git a/packages/core/src/Drawer/hooks/useSnap.ts b/packages/core/src/Drawer/hooks/useSnap.ts index 370971872..6e8971890 100644 --- a/packages/core/src/Drawer/hooks/useSnap.ts +++ b/packages/core/src/Drawer/hooks/useSnap.ts @@ -19,22 +19,43 @@ export function useSnap(snapHeights, snapDimensions) { const [snapPosition, setSnapPosition] = useState(MIDDLE) const handleSnap = (...args) => { + const pointerType = args?.[0]?.pointerType // mouse, touch, etc. + const type = args?.[0]?.type // click, pointerup (drag), pointercancel (scroll) const info = args?.[1] const scrollOffset = info.offset.y const SCROLL_DOWN = scrollOffset > SCROLL_THRESHOLD const SCROLL_UP = scrollOffset < -SCROLL_THRESHOLD - // Scroll down logic - if (SCROLL_DOWN) { - if (snapPosition === TOP) setSnapPosition(MIDDLE) - if (snapPosition === MIDDLE) setSnapPosition(BOTTOM) - } - - // Scroll up logic - else if (SCROLL_UP) { - if (snapPosition === BOTTOM) setSnapPosition(MIDDLE) - if (snapPosition === MIDDLE) setSnapPosition(TOP) + /** + * Differentiating between content scrolling and container dragging on mobile: + * + * 1. Content scrolling: + * - Triggered by touch events + * - Has a 'pointercancel' event type + * + * 2. Container dragging: + * - Should not occur accidentally during content scrolling + * - Has a 'pointerup' event type + * + * To prevent unintended container dragging, we only allow + * dragging when the event type is specifically 'pointerup'. + * This ensures smooth content scrolling without accidental + * container movement. + */ + + if (pointerType === 'touch' && type === 'pointerup') { + // Scroll down logic + if (SCROLL_DOWN) { + if (snapPosition === TOP) setSnapPosition(MIDDLE) + if (snapPosition === MIDDLE) setSnapPosition(BOTTOM) + } + + // Scroll up logic + else if (SCROLL_UP) { + if (snapPosition === BOTTOM) setSnapPosition(MIDDLE) + if (snapPosition === MIDDLE) setSnapPosition(TOP) + } } }