From 46130fed1ad43c2e3f8e86b2c68cd9ad1c630b07 Mon Sep 17 00:00:00 2001
From: Kevin <83264008+coolestKev@users.noreply.github.com>
Date: Tue, 7 Jan 2025 11:48:12 -0500
Subject: [PATCH] Task/htl 113692 limit dragging to header only (#1545)
* task(HTL-113692): Limit dragging behavior to header only
* task(HTL-113692): Limit drawer drag interaction to header only
* task(HTL-113692): Fix coverage
---
...gging-to-header-only_2025-01-07-05-13.json | 10 +++++
packages/core/src/Drawer/Drawer.stories.tsx | 1 -
packages/core/src/Drawer/Drawer.tsx | 19 ++++++++-
packages/core/src/Drawer/hooks/useSnap.ts | 42 +++++++++----------
4 files changed, 46 insertions(+), 26 deletions(-)
create mode 100644 common/changes/pcln-design-system/task-HTL-113692-limit-dragging-to-header-only_2025-01-07-05-13.json
diff --git a/common/changes/pcln-design-system/task-HTL-113692-limit-dragging-to-header-only_2025-01-07-05-13.json b/common/changes/pcln-design-system/task-HTL-113692-limit-dragging-to-header-only_2025-01-07-05-13.json
new file mode 100644
index 000000000..d3939e145
--- /dev/null
+++ b/common/changes/pcln-design-system/task-HTL-113692-limit-dragging-to-header-only_2025-01-07-05-13.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "pcln-design-system",
+ "comment": "Drawer is now draggable when user only drags the header, not the content",
+ "type": "patch"
+ }
+ ],
+ "packageName": "pcln-design-system"
+}
\ No newline at end of file
diff --git a/packages/core/src/Drawer/Drawer.stories.tsx b/packages/core/src/Drawer/Drawer.stories.tsx
index 6f35509c5..3562c5ebe 100644
--- a/packages/core/src/Drawer/Drawer.stories.tsx
+++ b/packages/core/src/Drawer/Drawer.stories.tsx
@@ -245,7 +245,6 @@ function DrawerScrollable(props) {
height='100vh'
style={{ backgroundColor: 'grey', height: '100vh', position: 'relative' }}
>
- Note: Mobile only feature - Please test on browser iOS/android device emulator
Previous position: {snapState.prevSnapPosition}
Current position: {snapState.currSnapPosition}
diff --git a/packages/core/src/Drawer/Drawer.tsx b/packages/core/src/Drawer/Drawer.tsx
index c4cf64fb3..5d76724ff 100644
--- a/packages/core/src/Drawer/Drawer.tsx
+++ b/packages/core/src/Drawer/Drawer.tsx
@@ -4,7 +4,7 @@ import { Flex } from '../Flex/Flex'
import { Text } from '../Text/Text'
import { DrawerRoot, DrawerWrapper, HeaderButton } from './Drawer.styled'
import { ChevronDown, Close } from 'pcln-icons'
-import { AnimatePresence, motion } from 'framer-motion'
+import { AnimatePresence, motion, useDragControls } from 'framer-motion'
import { SpaceProps, LayoutProps } from 'styled-system'
import { useScrollWithShadow } from '../useScrollWithShadows/useScrollWithShadow'
import { theme } from '../theme'
@@ -72,6 +72,8 @@ export const Drawer: React.FC = ({
const { boxShadow, onScrollHandler } = useScrollWithShadow()
const { snapPosition, handleSnap } = useSnap(snapHeights, snapDimensions, onSnapPositionChange)
const SnapContainer = snapHeights ? motion.div : 'div'
+ const headerRef = React.useRef(null)
+ const dragControls = useDragControls()
return (
= ({
dragConstraints={{ top: 0, bottom: 0 }}
{...(snapHeights ? { onDragEnd: handleSnap } : {})}
data-testid='snap-container'
+ dragControls={dragControls}
+ dragListener={false}
>
{isOpen && (
@@ -124,7 +128,18 @@ export const Drawer: React.FC = ({
>
{(heading || onClose || onCollapse) && (
-
+ {
+ if (snapHeights) {
+ dragControls.start(e)
+ }
+ }}
+ flexDirection='column'
+ style={{ touchAction: 'none' }}
+ data-testid='drawer-header-container'
+ >
{typeof heading === 'string' ? (
diff --git a/packages/core/src/Drawer/hooks/useSnap.ts b/packages/core/src/Drawer/hooks/useSnap.ts
index 67b558f5a..ce8c6d3eb 100644
--- a/packages/core/src/Drawer/hooks/useSnap.ts
+++ b/packages/core/src/Drawer/hooks/useSnap.ts
@@ -20,8 +20,6 @@ export function useSnap(snapHeights, snapDimensions, onSnapPositionChange) {
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
@@ -45,29 +43,27 @@ export function useSnap(snapHeights, snapDimensions, onSnapPositionChange) {
* container movement.
*/
- if (pointerType === 'touch' && type === 'pointerup') {
- // Scroll down logic
- if (SCROLL_DOWN) {
- if (snapPosition === TOP) {
- setSnapPosition(MIDDLE)
- onSnapPositionChange({ prevSnapPosition: 'TOP', currSnapPosition: 'MIDDLE' })
- }
- if (snapPosition === MIDDLE) {
- setSnapPosition(BOTTOM)
- onSnapPositionChange({ prevSnapPosition: 'MIDDLE', currSnapPosition: 'BOTTOM' })
- }
+ // Scroll down logic
+ if (SCROLL_DOWN) {
+ if (snapPosition === TOP) {
+ setSnapPosition(MIDDLE)
+ onSnapPositionChange({ prevSnapPosition: 'TOP', currSnapPosition: 'MIDDLE' })
}
+ if (snapPosition === MIDDLE) {
+ setSnapPosition(BOTTOM)
+ onSnapPositionChange({ prevSnapPosition: 'MIDDLE', currSnapPosition: 'BOTTOM' })
+ }
+ }
- // Scroll up logic
- else if (SCROLL_UP) {
- if (snapPosition === BOTTOM) {
- setSnapPosition(MIDDLE)
- onSnapPositionChange({ prevSnapPosition: 'BOTTOM', currSnapPosition: 'MIDDLE' })
- }
- if (snapPosition === MIDDLE) {
- setSnapPosition(TOP)
- onSnapPositionChange({ prevSnapPosition: 'MIDDLE', currSnapPosition: 'TOP' })
- }
+ // Scroll up logic
+ else if (SCROLL_UP) {
+ if (snapPosition === BOTTOM) {
+ setSnapPosition(MIDDLE)
+ onSnapPositionChange({ prevSnapPosition: 'BOTTOM', currSnapPosition: 'MIDDLE' })
+ }
+ if (snapPosition === MIDDLE) {
+ setSnapPosition(TOP)
+ onSnapPositionChange({ prevSnapPosition: 'MIDDLE', currSnapPosition: 'TOP' })
}
}
}