Commit b283dbd
feat: hub page discovery tabs A/B test (MetaMask#29193)
## **Description**
Implements the treatment UI for the
`coreMCU589AbtestHubPageDiscoveryTabs` A/B test
When the treatment variant is active, the homepage replaces the standard
scrollable layout with a top-tab navigation bar exposing three
verticals:
- **Portfolio:** existing homepage sections with balance header and
pull-to-refresh
- **Perpetuals:** `PerpsHomeView` wrapped in connection + stream
providers
- **Predictions:** `PredictFeed` wrapped in preview sheet provider
When the control variant is active (or the flag is absent), the existing
homepage layout is fully preserved.
Key implementation details:
- `HomepageDiscoveryTabs`: new component that owns tab layout, per-tab
gradient crossfade, and wallet header hide/show coordination across all
three tabs
- `TabsList` — design-system tab primitive with `keepMounted` support.
Perpetuals and Predictions both use `keepMounted={false}`:
- **Performance**: both screens have a heavy hydration cost on first
mount; keeping them alive while invisible wastes resources on tabs the
user may never visit
- **Open connections**: `PerpsHomeView` establishes WebSocket channels
for live market data via its stream providers on mount; leaving these
running in the background wastes bandwidth and server-side connection
slots
- **Memory**: `PredictFeed` and its preview sheet provider hold feed
state that can safely be discarded between visits
- Portfolio uses `keepMounted={true}` (the default) since it is the
landing tab and its scroll position and section state should survive
switching away and back
- Wallet header animates up/down on scroll via Reanimated shared values;
icon collapse and gradient opacity are synced via
`TabIconAnimationContext`
- Scroll event forwarding keeps existing `HOME_VIEWED` section analytics
working in the Portfolio tab
- A/B gating is handled by `useABTest(HUB_PAGE_DISCOVERY_TABS_AB_KEY)`
[Figma
Design](https://www.figma.com/design/z0panHXrMSMUSof2SaPkd4/Home-2026?m=auto&node-id=4280-62214&t=AAKr2hzmyPx57F4Y-1)
for reference. Only difference between this UI and the Figma is that the
tabs take up the entire space
## **Changelog**
CHANGELOG entry:null
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-591
## **Manual testing steps**
```gherkin
Feature: Hub Page Discovery Tabs
Scenario: treatment variant shows top tabs
Given the coreMCU589AbtestHubPageDiscoveryTabs flag is set to "treatment"
When user opens the app to the Wallet screen
Then three tabs are visible: Portfolio, Perpetuals, Predictions
And switching between tabs is smooth with no layout shift
And the wallet header hides on scroll and restores on tab switch
And pull-to-refresh works on the Portfolio tab
Scenario: control variant preserves existing layout
Given the coreMCU589AbtestHubPageDiscoveryTabs flag is set to "control"
When user opens the app to the Wallet screen
Then the existing homepage layout is shown with no tabs
```
## **Screenshots/Recordings**
### iOS
Dark Mode
https://github.com/user-attachments/assets/7df6a46d-b3b3-44cc-a697-b796581dd759
Light Mode (No Gradient)
https://github.com/user-attachments/assets/97b1f901-6092-42f9-926c-e8e6785c6f4e
### Android
Dark Mode
https://github.com/user-attachments/assets/4232f3fc-a47c-4516-93c2-104e4a3fb5cb
Light Mode (No Gradient)
https://github.com/user-attachments/assets/3f11dd8f-696f-438e-9867-1b08dc69200d
### **Before**
`~`
### **After**
`~`
## **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.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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]
> **Medium Risk**
> Introduces a new A/B-test-gated navigation structure and shared header
animation/scroll handling on the Wallet home screen, which could affect
core navigation and scroll/refresh behavior. Risk is mitigated by
control-path preservation and added unit coverage, but Reanimated
worklet interactions and tab switching edge cases remain sensitive.
>
> **Overview**
> When the Hub Page Discovery Tabs A/B test is in *treatment* (and
homepage sections are enabled), Wallet home now renders a new top-level
`HomepageDiscoveryTabs` experience with three tabs: Portfolio,
Perpetuals (`PerpsHomeView`), and Predictions (`PredictFeed`). The
control path preserves the existing scroll layout.
>
> Adds `useDiscoveryScrollManager`, a Reanimated-backed hook that
hides/shows the shared Wallet header based on scroll threshold, restores
per-tab header state on tab entry, forwards scroll events back to JS
(for analytics), and emits `onHeaderHiddenChange` to sync sibling
animations.
>
> Updates `Wallet` to measure/animate the header via shared values, pass
refresh/portfolio header/scroll callbacks into the new tabs view, and
crossfade a dark-mode gradient overlay per active tab. `PerpsHomeView`
and `PredictFeed` gain `hideHeader` and header-sync props, and
`useFeedScrollManager` can now notify header hidden/show changes; tests
are added/updated across these components and the new hook.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
38e679d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>1 parent 584d490 commit b283dbd
13 files changed
Lines changed: 2056 additions & 179 deletions
File tree
- app/components
- UI
- Perps/Views/PerpsHomeView
- Predict
- hooks
- views/PredictFeed
- Views
- Homepage/components/HomepageDiscoveryTabs
- Wallet
Lines changed: 92 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
7 | 26 | | |
8 | 27 | | |
9 | 28 | | |
| |||
877 | 896 | | |
878 | 897 | | |
879 | 898 | | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
880 | 972 | | |
Lines changed: 66 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
60 | 62 | | |
61 | 63 | | |
62 | 64 | | |
| |||
72 | 74 | | |
73 | 75 | | |
74 | 76 | | |
75 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
76 | 94 | | |
77 | 95 | | |
78 | 96 | | |
| |||
124 | 142 | | |
125 | 143 | | |
126 | 144 | | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
127 | 177 | | |
128 | 178 | | |
129 | 179 | | |
| |||
417 | 467 | | |
418 | 468 | | |
419 | 469 | | |
420 | | - | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
421 | 474 | | |
422 | | - | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
427 | 482 | | |
428 | 483 | | |
429 | | - | |
| 484 | + | |
430 | 485 | | |
431 | 486 | | |
432 | 487 | | |
433 | | - | |
| 488 | + | |
434 | 489 | | |
435 | 490 | | |
436 | 491 | | |
| |||
553 | 608 | | |
554 | 609 | | |
555 | 610 | | |
556 | | - | |
| 611 | + | |
557 | 612 | | |
558 | 613 | | |
559 | 614 | | |
| |||
0 commit comments