Skip to content

fix(money): scroll 'Your balance' heading with content (MUSD-779)#29863

Merged
Kureev merged 2 commits into
mainfrom
kureev/MUSD-779
May 7, 2026
Merged

fix(money): scroll 'Your balance' heading with content (MUSD-779)#29863
Kureev merged 2 commits into
mainfrom
kureev/MUSD-779

Conversation

@Kureev

@Kureev Kureev commented May 7, 2026

Copy link
Copy Markdown
Contributor

Description

The "Your balance" heading on the Money Hub screen (CashTokensFullView) was rendered between the screen header and the scrollable list, leaving it pinned at the top while content scrolled beneath it. This created a visually disconnected UX between the heading and the list.

The heading is now moved into each scrollable container so it scrolls naturally with the rest of the page:

  • Funded path: passed as ListHeaderComponent of the FlashList inside <TokenList>.
  • Empty-state path: rendered as the first child of the existing ScrollView.
  • Skeleton path: rendered as the first child of the skeleton's ScrollView.

To reach FlashList's header slot from the screen, an additive listHeaderComponent prop was added to <Tokens> and <TokenList>, mirroring the existing listFooterComponent pattern (opt-in, no behavior change for existing callers). A small wrapEdgeNode helper deduplicates the -mx-4 padding-compensation that header and footer both need in isFullView mode.

Note: <Tokens> / <TokenList> belong to the wallet team. Touching them was the minimal way to reach FlashList's header slot — flagging for wallet-team awareness during review.

Changelog

CHANGELOG entry: Fixed a bug where the "Your balance" heading on the Money Hub stayed pinned to the top of the screen instead of scrolling with the content.

Related issues

Fixes: MUSD-779

Manual testing steps

```gherkin
Feature: Money Hub Your balance heading scrolls with content

Scenario: user with mUSD scrolls the Money Hub
Given the user has mUSD balance on at least one chain
And the user is on the Money Hub
When the user scrolls down
Then the "Your balance" heading scrolls off-screen with the rest of the content
When the user scrolls back to the top
Then the "Your balance" heading reappears in flow above the mUSD list

Scenario: user without mUSD scrolls the Money Hub empty state
Given the user has no mUSD balance
And the user is on the Money Hub
When the user scrolls down
Then the "Your balance" heading scrolls off-screen with the empty-state content
```

Screenshots/Recordings

Before

After

Simulator.Screen.Recording.-.iPhone.16.Pro.26.3.-.2026-05-07.at.15.30.12.mov

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
  • I've tested with a power user scenario
  • I've instrumented key operations with Sentry traces for production performance metrics

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

Low Risk
Low risk UI/layout change that threads a new optional listHeaderComponent prop through Tokens/TokenList; main risk is minor rendering/padding regressions in full-view/empty-state paths.

Overview
Fixes Money Hub (CashTokensFullView) so the "Your balance" heading scrolls with the token content instead of staying pinned.

This adds an optional listHeaderComponent prop to Tokens and TokenList, wiring it through both the map-rendered list and the FlashList ListHeaderComponent, and updates the empty-state and skeleton ScrollViews to render the header at the top. It also deduplicates full-view edge padding compensation for both header and footer via wrapEdgeNode.

Reviewed by Cursor Bugbot for commit 8ab8ff1. Bugbot is set up for automated code reviews on this repo. Configure here.

The heading was rendered between the screen header and the scrollable
list, leaving it pinned while the content scrolled beneath it. Move it
into each scroll container (FlashList ListHeaderComponent for the
funded path, inline inside the empty-state and skeleton ScrollViews)
so it scrolls naturally with the rest of the page.

To reach FlashList's header slot from the screen, an additive
listHeaderComponent prop was added to <Tokens> and <TokenList>,
mirroring the existing listFooterComponent pattern.
@Kureev Kureev added the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 7, 2026
@github-actions

github-actions Bot commented May 7, 2026

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.

@github-actions github-actions Bot added the size-S label May 7, 2026
@Kureev Kureev marked this pull request as ready for review May 7, 2026 13:58
@Kureev Kureev requested a review from a team as a code owner May 7, 2026 13:58

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b2720ea. Configure here.

Comment thread app/components/UI/Tokens/index.tsx
…pty state (MUSD-779)

When the user has mUSD on some chain but the active network filter excludes it, <Tokens> takes its internal empty-state branch. That branch wraps the empty state in a ScrollView when listFooterComponent or refreshControl is passed, but did not render listHeaderComponent. Include it so the heading remains visible in this case.

Caught by Cursor Bugbot on PR review.
@Kureev Kureev self-assigned this May 7, 2026
@Kureev Kureev removed the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 7, 2026
@Kureev Kureev enabled auto-merge May 7, 2026 15:48
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeMoney
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 82%
click to see 🤖 AI reasoning details

E2E Test Selection:
The changes are focused on:

  1. Adding a listHeaderComponent prop to TokenList and Tokens components (additive, backward-compatible change)
  2. Refactoring CashTokensFullView to pass the "Your balance" heading as listHeaderComponent instead of rendering it inline above the token list - this is a UI layout refactor for the Money Hub (MetaMask Card) feature
  3. Updating CashTokensFullViewSkeleton to accept and render the listHeaderComponent
  4. Updating unit tests accordingly

The CashTokensFullView is the Money Hub screen (MetaMask Card feature), so SmokeMoney is the primary tag to validate this change. The SmokeMoney tests cover Card Home flows which exercise this view.

The Tokens component change is additive (new optional prop with no default behavior change), so it should not break any existing token list rendering in other flows. No controller, navigation, or core infrastructure changes are involved.

No other tags are needed because:

  • The listHeaderComponent prop is optional and defaults to undefined, so all existing callers of Tokens are unaffected
  • The wrapEdgeNode refactor in TokenList preserves existing footer behavior exactly
  • No wallet platform, swap, stake, or other feature flows are impacted

Performance Test Selection:
The changes are a UI layout refactor - moving a heading element from inline rendering to being passed as a listHeaderComponent prop. This is a minor structural change that doesn't affect rendering performance in a measurable way. No new data fetching, state management changes, or list rendering logic changes that would impact performance metrics.

View GitHub Actions results

@sonarqubecloud

sonarqubecloud Bot commented May 7, 2026

Copy link
Copy Markdown

@Kureev Kureev added this pull request to the merge queue May 7, 2026
Merged via the queue into main with commit 2195a67 May 7, 2026
157 of 158 checks passed
@Kureev Kureev deleted the kureev/MUSD-779 branch May 7, 2026 18:14
@github-actions github-actions Bot locked and limited conversation to collaborators May 7, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.77.0 Issue or pull request that will be included in release 7.77.0 label May 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.77.0 Issue or pull request that will be included in release 7.77.0 size-S team-earn

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants