Skip to content

Pan gesture release triggers underlying Pressable onPress despite gesture activation #3559

@Decryptu

Description

@Decryptu

Description

When using a horizontal pan gesture for a carousel, releasing the finger after swiping triggers onPress events on underlying Pressable components, even when the pan gesture has been active and moved significantly. This does not happen with vertical scrolling (ScrollView/FlatList), which properly prevents click-through.

Environment

  • React Native Gesture Handler version: 2.25.0
  • React Native version: Latest (Expo SDK)
  • Platform: Both iOS and Android
  • Using: TypeScript, Expo Router, react-native-reanimated

Expected Behavior

When a pan gesture has been active and the user has swiped horizontally, releasing the finger should NOT trigger onPress events on underlying components, similar to how ScrollView prevents clicks after scrolling.

Actual Behavior

Horizontal swipe gesture release consistently triggers onPress on underlying Pressable components, causing unwanted navigation/actions.

Code Example

// Carousel with pan gesture
const panGesture = Gesture.Pan()
  .minDistance(15)
  .onBegin(() => {
    startTranslateX.value = translateX.value;
  })
  .onUpdate((e) => {
    translateX.value = startTranslateX.value + e.translationX;
  })
  .onEnd((e) => {
    // Handle page change logic
  });

// Underlying component that gets clicked incorrectly
<Pressable onPress={() => router.push('/article')}>
  <ArticleCard />
</Pressable>

What We've Tried

Original attempts:

  1. setTimeout delays in gesture onEnd/onFinalize → App crashes immediately on swipe release
  2. Shared values to track gesture state → Still triggers clicks, no prevention
  3. minDistance + gesture activation thresholds → Still clicks through
  4. Press duration timing in ArticleCard (onPressIn/onPressOut) → Still triggers on release
  5. Various gesture configurations → Either crashes or doesn't prevent click-through

Additional attempts:

  1. Tracking gesture state with useSharedValue and pointerEvents: 'none' → Still triggers clicks
  2. Distance-based swipe detection with conditional blocking → Causes crashes on gesture end
  3. Combining minDistance with state tracking → No improvement
  4. Manual press handling with gesture state checks → Unreliable and still allows click-through

Comparison with ScrollView

ScrollView correctly prevents underlying touch events when scrolling occurs, but horizontal pan gestures do not exhibit the same behavior. This suggests the issue is in how pan gestures handle touch event propagation on release.

Expected Solution

Pan gestures should automatically prevent underlying touch events when:

  1. The gesture has been activated (moved beyond minDistance)
  2. The finger is released after an active gesture
  3. Similar to how ScrollView prevents clicks after scrolling

Additional Context

This is a common UX pattern (horizontal carousels with clickable content) and the current behavior makes it nearly impossible to implement reliably. Users expect that after swiping, they won't accidentally trigger actions on the content they swiped over.

The fact that vertical scrolling (FlatList/ScrollView) handles this correctly suggests there's an inconsistency in gesture handling between different gesture types.

Additional Technical Details:

  • Using Expo Router for navigation
  • TypeScript project
  • NativeWind for styling
  • The issue occurs regardless of whether minDistance is set on the pan gesture
  • FlatList vertical scrolling within the same interface works correctly (doesn't trigger onPress after scrolling)

Steps to Reproduce

With Expo Snack

  1. Open the Expo Snack
  2. Start a horizontal swipe gesture to change pages
  3. While performing the horizontal swipe, release your finger on top of one of the colored cards
  4. BUG: The card's onPress event fires even though you were swiping, not intending to press the card

Expected behavior

When performing a horizontal swipe gesture, releasing the finger on underlying Pressable components should NOT trigger their onPress events, similar to how ScrollView behaves.

Actual behavior

The underlying Pressable components' onPress events are triggered when releasing the finger after a horizontal swipe gesture, causing unintended navigation/actions.

Additional context

  • This only happens with horizontal pan gestures
  • Vertical scrolling (like in ScrollView) does not have this issue
  • The issue occurs on both iOS and Android
  • This makes horizontal carousels with clickable content unusable

With real repo

  1. Clone the repositories:

    git clone https://github.com/Decryptu/CryptoastAppCache.git -b dev
    git clone https://github.com/Decryptu/CryptoastApp.git -b dev
  2. Start the cache server (dev branch):

    cd CryptoastAppCache
    docker-compose up
  3. Run the Expo app (dev branch):

    cd CryptoastApp
    npm install
    expo start
  4. Navigate to the Home tab

  5. Perform a horizontal swipe gesture to change sections

  6. Release finger on top of an article card

  7. Bug: Article opens despite having just performed a swipe gesture

Note: Vertical scrolling (within the FlatList) correctly prevents click-through behavior.

A link to a Gist, an Expo Snack or a link to a repository based on this template that reproduces the bug.

https://snack.expo.dev/@decryptu/pan-gesture-release-triggers

Gesture Handler version

~2.24.0

React Native version

0.79.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Using Expo Go

Architecture

New Architecture (Fabric)

Build type

Debug mode

Device

Real device

Device model

Apple iPhone 13 Pro

Acknowledgements

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions