Skip to content

fix: fall back to other axis when main scroll direction is not scrollable#153

Open
es27 wants to merge 1 commit intotheKashey:masterfrom
es27:fix/fallback-scroll-axis-on-diagonal-swipe
Open

fix: fall back to other axis when main scroll direction is not scrollable#153
es27 wants to merge 1 commit intotheKashey:masterfrom
es27:fix/fallback-scroll-axis-on-diagonal-swipe

Conversation

@es27
Copy link

@es27 es27 commented Mar 3, 2026

Problem

On mobile devices, vertical scrolling inside modals/dialogs is blocked
when the user's finger moves with a slight horizontal offset during a swipe.

shouldCancelEvent in SideEffect.tsx determines moveDirection from
the initial touch delta:

const moveDirection = Math.abs(deltaX) > Math.abs(deltaY) ? 'h' : 'v';

When the horizontal component is even marginally larger, moveDirection
is 'h'. Then locationCouldBeScrolled('h', target) finds no
horizontally scrollable ancestor and the function returns true
(cancel), calling preventDefault() on the touch event. This kills
the vertical scroll.

This is easily reproducible on the Radix UI docs page itself
(radix-ui.com/primitives/docs/components/dialog)  open a Dialog
on a real mobile device and try scrolling with a natural (slightly
diagonal) swipe.

Fix

Before returning true (block), check if the other axis is
scrollable. If it is, switch currentAxis to that axis and continue
with normal scroll handling instead of blocking.

if (!canBeScrolledInMainDirection) {
  const otherAxis = moveDirection === 'v' ? 'h' : 'v';
  if (locationCouldBeScrolled(otherAxis, target)) {
    currentAxis = otherAxis;
    canBeScrolledInMainDirection = true;
  } else {
    return true;
  }
}

  to other axis when main scroll direction is not scrollable

  When a touch gesture has a slightly larger horizontal delta than vertical
  (common during natural diagonal swipes), shouldCancelEvent determines
  moveDirection as 'h'. If no element in the hierarchy is horizontally
  scrollable, the event is immediately cancelled via preventDefault() —
  even though the user's intent is to scroll vertically.

  This change checks the perpendicular axis before blocking: if the other
  direction is scrollable, the gesture is allowed and the axis is switched
  accordingly. The event is only cancelled when neither axis can be scrolled.

  Fixes scroll blocking in modals/dialogs on mobile devices when the user's
  finger drifts slightly off the vertical axis during a swipe.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant