Skip to content

fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity cp-7.57.0#21146

Merged
brianacnguyen merged 10 commits into
mainfrom
fix/touchable-gesture-android-3
Oct 15, 2025
Merged

fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity cp-7.57.0#21146
brianacnguyen merged 10 commits into
mainfrom
fix/touchable-gesture-android-3

Conversation

@brianacnguyen

@brianacnguyen brianacnguyen commented Oct 14, 2025

Copy link
Copy Markdown
Contributor

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

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

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.

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.

Written by Cursor Bugbot. This will update automatically on new commits. Configure here.


@brianacnguyen brianacnguyen requested review from a team as code owners October 14, 2025 17:31
@github-actions

Copy link
Copy Markdown
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.

@brianacnguyen brianacnguyen marked this pull request as draft October 14, 2025 17:31
@metamaskbot metamaskbot added the team-design-system All issues relating to design system in Mobile label Oct 14, 2025
cursor[bot]

This comment was marked as outdated.

@brianacnguyen brianacnguyen changed the title Draft: fix: conditionally apply onPress for Accessibility mode for Android touchables fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity Oct 15, 2025
@brianacnguyen brianacnguyen marked this pull request as ready for review October 15, 2025 01:28
@brianacnguyen brianacnguyen self-assigned this Oct 15, 2025
@brianacnguyen brianacnguyen added needs-qa Any New Features that needs a full manual QA prior to being added to a release. skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. labels Oct 15, 2025
cursor[bot]

This comment was marked as outdated.

@Unik0rnMaggie

Unik0rnMaggie commented Oct 15, 2025

Copy link
Copy Markdown
Contributor

Testing the latest QA build of this fix:

  1. Buy and deposit still not working: clicking on a token leads back to home page

  2. The issues with accounts list highlighted before are still present:

  • Accounts list Details button is unresponsive

  • Edit account name not possible: clicking on edit account brings up the keyboard, but account cannot be edited

  • Account names did not preserve when using this build

  • Clicking on Wallet details from Account details is unresponsive

  1. Unknown address when clicking the Receive button
buy-deposit.-.option.3.fix.mp4
Option.3.fix.-.Accounts.list.mp4
screenshot-1760541153946

@Unik0rnMaggie Unik0rnMaggie added QA'd - Issues Found QA has been complete, however issues have been discovered that need to be addressed and removed needs-qa Any New Features that needs a full manual QA prior to being added to a release. labels Oct 15, 2025
@github-actions github-actions Bot added size-L and removed size-M labels Oct 15, 2025
cursor[bot]

This comment was marked as outdated.

@brianacnguyen brianacnguyen requested a review from a team as a code owner October 15, 2025 13:23
@brianacnguyen brianacnguyen requested a review from a team as a code owner October 15, 2025 13:23
cursor[bot]

This comment was marked as outdated.

@brianacnguyen brianacnguyen changed the title fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity fix: conditionally apply onPress for Accessibility mode for Android TouchableOpacity cp-7.57.0 Oct 15, 2025
@Unik0rnMaggie

Copy link
Copy Markdown
Contributor

Testing on the latest QA build from here :

  1. Buy -deposit-withdraw : clicking on any token works
  2. Accounts List issues from above still present
  3. Unknown address when clicking the Receive button
buy-deposit.fixed.mp4
withdraw.fix.mp4

@sleepytanya

Copy link
Copy Markdown
Contributor

Seeing the same as @Unik0rnMaggie - Buy-Deposit-Withdraw big fixed.
Remaining problems will be fixed in the following react native patch:

  • user can't dismiss 'Got it' button in Perps (token details)
  • account list issues
  • unknown address / network when clicking Receive button.

Test build

Screen_Recording_20251015_122201_MetaMask.QA.mp4

@sleepytanya sleepytanya added the QA Passed QA testing has been completed and passed label Oct 15, 2025
@brianacnguyen brianacnguyen removed the QA'd - Issues Found QA has been complete, however issues have been discovered that need to be addressed label Oct 15, 2025
@brianacnguyen brianacnguyen force-pushed the fix/touchable-gesture-android-3 branch from 41ca267 to f04dfc7 Compare October 15, 2025 16:54
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
31.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Refactors press handling to remove timestamp-based coordination and introduce accessibility-aware gesture vs onPress usage, with numerous snapshot updates reflecting changed props. Key changes: removal of useCoordinatedPress hook in Perps components, addition of AccessibilityInfo-driven conditional onPress logic in ButtonBase/ListItemSelect/ListItemMultiSelect, and updated test-mode fallbacks. Snapshots updated to reflect conditional omission or mocking of onPress.

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
PressablePerpsComponent/PressablePerpsComponent.tsx Removes deprecated coordinated press hook, simplifying export.
PerpsCard/PerpsCard.tsx Drops coordinatedPress usage; directly invokes handler.
PerpsTabView/PerpsTabView.tsx Removes coordinatedPress; direct press invocation.
ListItemSelect/ListItemSelect.tsx Adds accessibility state tracking and gesture/onPress bifurcation; removes coordination logic.
ListItemMultiSelect/ListItemMultiSelect.tsx Similar accessibility handling plus iOS checkbox timing coordination refactor.
ButtonBase/ButtonBase.tsx Implements accessibility-aware gesture handling and removes coordination logic.
Various *.snap files Snapshot updates reflecting removed or mocked onPress handlers under new logic.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@georgewrmarshall georgewrmarshall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work addressing the button responsiveness issues! Approving to unblock ✅

There seems to be significant DRY violations that could be addressed in a follow up. The custom TouchableOpacity wrapper is duplicated many times. Could we create a hook centralize the accessibility and gesture logic?

Excellent problem solving! Technical approach is strong and just needs some architectural cleanup. 👍

@gambinish gambinish left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests well on Android. Opened a few positions on Perps tab and was able to navigate them. Changing tabs worked well.

@brianacnguyen brianacnguyen added this pull request to the merge queue Oct 15, 2025
@brianacnguyen

Copy link
Copy Markdown
Contributor Author

Great work addressing the button responsiveness issues! Approving to unblock ✅

There seems to be significant DRY violations that could be addressed in a follow up. The custom TouchableOpacity wrapper is duplicated many times. Could we create a hook centralize the accessibility and gesture logic?

Excellent problem solving! Technical approach is strong and just needs some architectural cleanup. 👍

Yes. The patch would reduce the duplicated problem

Merged via the queue into main with commit 1d32de9 Oct 15, 2025
91 of 92 checks passed
@brianacnguyen brianacnguyen deleted the fix/touchable-gesture-android-3 branch October 15, 2025 18:44
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 15, 2025
@metamaskbot metamaskbot added the release-7.58.0 Issue or pull request that will be included in release 7.58.0 label Oct 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

QA Passed QA testing has been completed and passed release-7.58.0 Issue or pull request that will be included in release 7.58.0 size-L skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-design-system All issues relating to design system in Mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: OnPress is called twice in ButtonBase

7 participants