diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx
index a5a645ab64..8d283c3c60 100644
--- a/src/components/Alert.tsx
+++ b/src/components/Alert.tsx
@@ -70,6 +70,7 @@ const Alert: FC = () => {
showXOnHover
onClose={alert.showCloseLink ? onClose : undefined}
calculatedHeight={popupRef.current?.getBoundingClientRect().height || 50}
+ swipeDownToDismiss
>
, 'className'>
>
@@ -44,6 +45,7 @@ const PopupBase = React.forwardRef(
calculatedHeight,
circledCloseButton,
showXOnHover,
+ swipeDownToDismiss,
...props
},
ref,
@@ -61,6 +63,7 @@ const PopupBase = React.forwardRef(
onDismissEnd: () => {
dispatch(alert(null))
},
+ swipeDown: swipeDownToDismiss,
})
const combinedRefs = useCombinedRefs(isTouch ? [useSwipeToDismissProps.ref, ref] : [ref])
diff --git a/src/hooks/useSwipeToDismiss.ts b/src/hooks/useSwipeToDismiss.ts
index 323c4594fb..c1333367ea 100644
--- a/src/hooks/useSwipeToDismiss.ts
+++ b/src/hooks/useSwipeToDismiss.ts
@@ -5,6 +5,7 @@ const defaultOptions = {
dx: 0,
snapbackDuration: 0.1,
snapbackEasing: 'ease-out',
+ swipeDown: false,
}
/** Custom hook to manage swipe to dismiss alerts. */
@@ -28,10 +29,13 @@ const useSwipeToDismiss = (
// easing function to animate the element back into place after releasing
snapbackEasing?: string
+
+ // whether to swipe down to dismiss (true) or swipe up (false)
+ swipeDown?: boolean
} = {},
) => {
// initialize default options
- const { dismissThreshold, dx, onDismiss, onDismissEnd, snapbackDuration, snapbackEasing } = {
+ const { dismissThreshold, dx, onDismiss, onDismissEnd, snapbackDuration, snapbackEasing, swipeDown } = {
...defaultOptions,
...options,
}
@@ -74,12 +78,16 @@ const useSwipeToDismiss = (
// check for dismiss threshold
// if specified as a percentage of height, use percentage of element height
const isPercentageOfHeight = typeof dismissThreshold === 'string' && dismissThreshold.endsWith('%')
- const dismissThresholdPx = isPercentageOfHeight
- ? (-parseFloat(dismissThreshold as string) * height) / 100
- : -parseFloat(dismissThreshold as string)
+ const thresholdValue = isPercentageOfHeight
+ ? (parseFloat(dismissThreshold as string) * height) / 100
+ : parseFloat(dismissThreshold as string)
+
+ // Check threshold based on swipe direction
+ const dismissThresholdPx = swipeDown ? thresholdValue : -thresholdValue
+ const shouldDismiss = swipeDown ? dy > dismissThresholdPx : dy < -dismissThresholdPx
- if (dy < dismissThresholdPx) {
- setDY(-height * 2)
+ if (shouldDismiss) {
+ setDY(swipeDown ? height * 2 : -height * 2)
onDismiss?.()
setTimeout(() => {
onDismissEnd?.()
@@ -98,11 +106,17 @@ const useSwipeToDismiss = (
const y = e.touches?.[0].pageY
const dy = y - y0
- // resist dragging down by taking the square root of positive dy
- const dyResistant = dy < 0 ? dy : Math.sqrt(dy)
+ // Apply resistance in the non-dismissal direction
+ const dyResistant = swipeDown
+ ? dy < 0
+ ? Math.sqrt(-dy) * -1
+ : dy // resist upward motion when swipeDown
+ : dy > 0
+ ? Math.sqrt(dy)
+ : dy // resist dragging down by taking square root of positive dy
setDY(dyResistant)
},
- [y0],
+ [y0, swipeDown],
)
return {