chore(runway): cherry-pick fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity cp-7.57.0#21221
Merged
Conversation
…sibility mode for Android TouchableOpacity cp-7.57.0 (#21146) ## **Description** This PR fixes critical button responsiveness issues in ScrollView and BottomSheet contexts by refactoring gesture handling and removing deprecated press coordination logic across the component library. **Problem:** - Buttons were unresponsive in ScrollView contexts on Android due to TouchableOpacity conflicts - Buttons in BottomSheet components (like "Got it", "Add funds", "Withdraw") had gesture handler conflicts with BottomSheet pan gestures - The existing `useCoordinatedPress` hook was causing double-firing issues and race conditions with accessibility features **Solution:** 1. **Gesture priority management**: Implemented `requireExternalGestureToFail()` with tight constraints (300ms max duration, 20px max delta) to allow buttons to work alongside BottomSheet gestures 2. **Accessibility-aware handling**: Implemented exclusive gesture handling - use gesture handler when accessibility is OFF, TouchableOpacity when accessibility is ON/UNKNOWN to prevent race conditions 3. **Simplified coordination**: Removed deprecated `useCoordinatedPress` hook and related timestamp-based coordination logic 4. **Test environment safety**: Added fallback to standard `RNTouchableOpacity` in test environments ## **Changelog** CHANGELOG entry: Fixed button responsiveness issues in ScrollView and BottomSheet contexts ## **Related issues** Fixes: #18704 ## **Manual testing steps** ```gherkin Feature: Button responsiveness in various contexts Scenario: user taps buttons in ScrollView contexts Given user is viewing buttons within a ScrollView on Android When user taps any button Then button should respond immediately without delay Scenario: user taps buttons in BottomSheet modals Given user sees a BottomSheet modal with action buttons When user taps action buttons (e.g., "Got it", "Add funds") Then buttons should respond without conflicting with sheet gestures Scenario: accessibility users interact with buttons Given screen reader is enabled When user taps any button Then button should respond using TouchableOpacity onPress (not gesture handler) And should not experience double-firing or race conditions Scenario: gesture handling in test environments Given app is running in test environment When tests interact with buttons Then buttons should use standard RNTouchableOpacity behavior ``` ## **Screenshots/Recordings** ### **Before** ### **After** ## **Technical Changes** ### **Core Components Updated:** - `ButtonBase.tsx` - Added gesture handler with `requireExternalGestureToFail()` and tight constraints, accessibility state tracking to prevent double-firing - `ListItemSelect.tsx` - Same gesture priority fix and accessibility handling - `ListItemMultiSelect.tsx` - Updated gesture handling while preserving iOS checkbox coordination - `PressablePerpsComponent.tsx` - Removed `useCoordinatedPress` hook (already compatible) ### **Perps Components Updated:** - `PerpsTabView.tsx` - Removed `useCoordinatedPress` usage, direct `onPress` calls - `PerpsCard.tsx` - Removed `useCoordinatedPress` usage, simplified press handling ### **Key Technical Improvements:** 1. **Gesture Conflict Resolution**: `requireExternalGestureToFail()` allows BottomSheet pan gestures to take priority when needed, while still detecting taps within tight constraints 2. **Accessibility Race Condition Fix**: Use `null` initial state for `isAccessibilityEnabled` to handle async updates safely; exclusive handling prevents double-firing 3. **Test Environment Compatibility**: Conditional fallback to standard TouchableOpacity in tests 4. **Performance**: Removed unnecessary coordination wrapper and timestamp tracking ### **Implementation Details:** - Gesture handler only fires when `isAccessibilityEnabled === false` (known OFF state) - TouchableOpacity `onPress` only fires when `isAccessibilityEnabled !== false` (ON or UNKNOWN state) - Tight gesture constraints: 300ms max duration, 20px max delta, single pointer only - `onEnd` lifecycle used (not `onStart`) to ensure complete gesture detection ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Makes Android touchables accessibility-aware with gesture priority management to avoid ScrollView and BottomSheet conflicts, removes press coordination logic, and simplifies Perps press handling with test-safe fallbacks. > > - **Component Library**: > - **`Buttons/Button/foundation/ButtonBase`**: Adds `AccessibilityInfo`-aware tap handling (gesture only when screen reader is off), `requireExternalGestureToFail()` with tight constraints (300ms, 20px delta), test-mode fallback to `RNTouchableOpacity`; implements exclusive `onPress` handling to prevent double-firing. > - **`ListItemSelect` / `ListItemMultiSelect`**: Mirrors accessibility-aware gesture handling with priority management; refactors iOS checkbox coordination; provides test-mode fallback and conditional `onPress` wiring. > - **Perps**: > - **`PressablePerpsComponent`**: Keeps platform-specific touchable; removes `useCoordinatedPress` hook. > - **`PerpsTabView` / `PerpsCard`**: Drops `useCoordinatedPress` usage; invoke handlers directly. > - **Tests**: > - Snapshot updates reflecting conditional `onPress` and test-mode behavior (`[MockFunction]`), across various UI snapshots. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot). This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> ---
Contributor
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
|
Collaborator
|
No release label on PR. Adding release label release-7.57.0 on PR, as PR was cherry-picked in branch 7.57.0. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
This PR fixes critical button responsiveness issues in ScrollView and
BottomSheet contexts by refactoring gesture handling and removing
deprecated press coordination logic across the component library.
Problem:
TouchableOpacity conflicts
"Withdraw") had gesture handler conflicts with BottomSheet pan gestures
useCoordinatedPresshook was causing double-firingissues and race conditions with accessibility features
Solution:
requireExternalGestureToFail()with tight constraints (300ms maxduration, 20px max delta) to allow buttons to work alongside BottomSheet
gestures
handling - use gesture handler when accessibility is OFF,
TouchableOpacity when accessibility is ON/UNKNOWN to prevent race
conditions
useCoordinatedPresshook and related timestamp-based coordination logic
RNTouchableOpacityin test environmentsChangelog
CHANGELOG entry: Fixed button responsiveness issues in ScrollView and
BottomSheet contexts
Related issues
Fixes: #18704
Manual testing steps
Screenshots/Recordings
Before
After
Technical Changes
Core Components Updated:
ButtonBase.tsx- Added gesture handler withrequireExternalGestureToFail()and tight constraints, accessibilitystate tracking to prevent double-firing
ListItemSelect.tsx- Same gesture priority fix and accessibilityhandling
ListItemMultiSelect.tsx- Updated gesture handling while preservingiOS checkbox coordination
PressablePerpsComponent.tsx- RemoveduseCoordinatedPresshook(already compatible)
Perps Components Updated:
PerpsTabView.tsx- RemoveduseCoordinatedPressusage, directonPresscallsPerpsCard.tsx- RemoveduseCoordinatedPressusage, simplifiedpress handling
Key Technical Improvements:
requireExternalGestureToFail()allows BottomSheet pan gestures to take priority when needed, while
still detecting taps within tight constraints
nullinitial state forisAccessibilityEnabledto handle async updates safely; exclusivehandling prevents double-firing
TouchableOpacity in tests
timestamp tracking
Implementation Details:
isAccessibilityEnabled === false(known OFF state)
onPressonly fires whenisAccessibilityEnabled !== false(ON or UNKNOWN state)pointer only
onEndlifecycle used (notonStart) to ensure complete gesturedetection
Pre-merge author checklist
Docs and MetaMask Mobile
Coding
Standards.
if applicable
guidelines).
Not required for external contributors.
Pre-merge reviewer checklist
app, test code being changed).
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Note
Adds accessibility-aware tap handling and removes timestamp-based press coordination to fix unresponsive/double-fired presses on Android across ButtonBase, list items, and Perps UI.
ButtonBase: Adds gesture handler (Tapwith tight constraints andrequireExternalGestureToFail) andAccessibilityInfo-based press routing; usesRNTouchableOpacityin tests; simplifiesonPress(removes timestamp coordination).ListItemSelectandListItemMultiSelectto match the new gesture/accessibility model; keep iOS checkbox coordination; provide platform-awareonPressdelegation.useCoordinatedPresshook and its usage inPerpsTabViewandPerpsCard; press now calls handlers directly.TouchablePerpsComponentremains as Android wrapper, with deprecated coordination hook removed.Written by Cursor Bugbot for commit da8ff6d. This will update automatically on new commits. Configure here.
--- 1d32de9