Skip to content

feat(perps): introduce perps tutorial#39693

Merged
geositta merged 24 commits intomainfrom
perps/learn-perps
Feb 14, 2026
Merged

feat(perps): introduce perps tutorial#39693
geositta merged 24 commits intomainfrom
perps/learn-perps

Conversation

@geositta
Copy link
Copy Markdown
Contributor

@geositta geositta commented Feb 1, 2026

Description

This PR introduces the Perps tutorial modal - a 6-step onboarding flow that educates users about perpetual futures trading. The implementation matches the design and text from MetaMask Mobile.

Features:
6-step tutorial flow with progress indicator
Rive animations for steps 2-6 with theme support (light/dark)
Static character image for the first step
Responsive layout that works across popup, side panel, and fullscreen modes
Redux state management for tutorial progress via ducks/perps
Left-aligned text matching mobile design
Skip and Continue navigation with proper state handling

New files:
ui/components/app/perps/perps-tutorial-modal/ - Modal and step components
ui/ducks/perps/tutorial.ts - Redux slice for tutorial state
ui/ducks/perps/selectors.ts - Redux selectors
app/images/riv_animations/perps-onboarding-carousel-*.riv - Rive animation files
app/images/perps-character.png - Static character image

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Added Perps tutorial modal with animated walkthrough explaining perpetual futures trading

Related issues

Fixes:

Manual testing steps

Test Steps:
Open the Perps Tutorial Modal
Navigate to the Perps tab
Trigger the tutorial modal (e.g., via "Learn Perps" button)
Test First Step (What Are Perps)
Verify title and description are left-aligned
Verify character image displays correctly
Verify "Continue" and "Skip" buttons are visible
Test Animation Steps (Steps 2-6)
Click Continue to navigate through each step
Verify Rive animations play correctly
Verify animations are not cut off on any edge
Test All Three Viewport Modes:
a) Side Panel Mode (~320px width)
Verify animations display correctly without horizontal cutoff
b) Popup Mode (~360px width)
Verify animations scale appropriately
c) Fullscreen Mode
Verify animations are constrained and not oversized
Test Dark/Light Theme
Switch between dark and light themes
Verify correct animation file loads for each theme
Test Navigation
Verify "Skip" closes the modal
Verify "Continue" progresses to next step
Verify final step completes the tutorial

Screenshots/Recordings

Before

After

LearnPerpsAll3Screens.mov

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

Medium Risk
Adds new Redux state and a modal flow that depends on Rive WASM/asset loading and environment-specific sizing; regressions would mainly affect Perps UI onboarding and performance/memory if animation cleanup/loading fails.

Overview
Adds a new 6-step Perps tutorial modal (progress indicator + static/animated visuals) and wires it into PerpsHomePage via the “Learn basics” entry to open the flow.

Introduces a new perpsTutorial Redux slice (open/active step/completed) with selectors and actions, updates root reducer/state snapshots, and adds new i18n strings plus component tests (including Rive animation loading/sizing across popup/sidepanel/fullscreen and light/dark themes).

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 1, 2026

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.

@metamaskbot metamaskbot added the team-perps Perps team label Feb 1, 2026
@metamaskbotv2
Copy link
Copy Markdown
Contributor

metamaskbotv2 bot commented Feb 1, 2026

✨ Files requiring CODEOWNER review ✨

🕵️ @MetaMask/extension-privacy-reviewers (1 files, +5 -0)
  • 📁 test/
    • 📁 e2e/
      • 📁 tests/
        • 📁 settings/
          • 📄 state-logs.json +5 -0

👨‍🔧 @MetaMask/perps (18 files, +1576 -6)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 perps/
          • 📁 perps-tutorial-modal/
            • 📁 steps/
              • 📄 ChooseLeverageStep.tsx +88 -0
              • 📄 CloseAnytimeStep.tsx +88 -0
              • 📄 GoLongShortStep.test.tsx +160 -0
              • 📄 GoLongShortStep.tsx +94 -0
              • 📄 ReadyToTradeStep.tsx +68 -0
              • 📄 WatchLiquidationStep.tsx +88 -0
              • 📄 WhatArePerpsStep.test.tsx +188 -0
              • 📄 WhatArePerpsStep.tsx +112 -0
              • 📄 index.ts +2 -0
              • 📄 PerpsTutorialAnimation.test.tsx +232 -0
              • 📄 PerpsTutorialAnimation.tsx +182 -0
              • 📄 PerpsTutorialModal.tsx +112 -0
              • 📄 ProgressIndicator.tsx +41 -0
            • 📄 index.ts +1 -0
    • 📁 ducks/
      • 📁 perps/
        • 📄 index.ts +16 -1
        • 📄 selectors.ts +10 -0
        • 📄 tutorial.ts +79 -0
    • 📁 pages/
      • 📁 perps/
        • 📄 perps-home-page.tsx +15 -5

🧪 @MetaMask/qa (1 files, +5 -0)
  • 📁 test/
    • 📁 e2e/
      • 📁 tests/
        • 📁 settings/
          • 📄 state-logs.json +5 -0

@metamaskbotv2
Copy link
Copy Markdown
Contributor

metamaskbotv2 bot commented Feb 4, 2026

Builds ready [f35f825]
UI Startup Metrics (1337 ± 105 ms)
PlatformBuildTypePageMetricTest Title (ms)Persona (ms)Mean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--13371113168710514151481
load--115093614159812201288
domContentLoaded--114192913959612121281
domInteractive--2716173232183
firstPaint--211621426231206369
backgroundConnect--21619526013222247
firstReactRender--1894052029
initialActions--108115
loadScripts--94373311779510161083
setupStore--1363961525
numNetworkReqs--231594211588
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--19031359600164418333334
load--11611006199917611551594
domContentLoaded--1147995199117511401579
domInteractive--35171462536101
firstPaint--1787346282240338
backgroundConnect--41128430233593411221
firstReactRender--24156282442
initialActions--105113
loadScripts--90476816511618931315
setupStore--1554661728
numNetworkReqs--1174727251146228
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--86568111431069411060
load--72660796194797898
domContentLoaded--72060495792793891
domInteractive--241597191980
firstPaint--1126033063151235
backgroundConnect--3819138224881
firstReactRender--1693961730
initialActions--104112
loadScripts--71760295591789889
setupStore--1266171228
numNetworkReqs--2315101211583
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1195842184720512591661
load--69860510681126941036
domContentLoaded--68959910611126831025
domInteractive--36172243233101
firstPaint--150671050148153390
backgroundConnect--1635339756160310
firstReactRender--20163132228
initialActions--103111
loadScripts--68659710521106811017
setupStore--1141931316
numNetworkReqs--1284930357153268
19--------
FirefoxBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--16961380230620518372049
load--14141181188116615561725
domContentLoaded--14131181188116615561725
domInteractive--783323746100164
firstPaint--------
backgroundConnect--832825253123193
firstReactRender--12102021315
initialActions--103112
loadScripts--13671166176814214611624
setupStore--194170271599
numNetworkReqs--241295221890
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--26801971391242428033695
load--14971180236824515972174
domContentLoaded--14971180236324515972174
domInteractive--1073445882113311
firstPaint--------
backgroundConnect--3051171611270342890
firstReactRender--19146981925
initialActions--102122
loadScripts--14491148234523115182092
setupStore--1268720181117626
numNetworkReqs--69371483295133
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--15901304207514316921834
load--13661120170410614471539
domContentLoaded--13651120170310614471539
domInteractive--882823748130159
firstPaint--------
backgroundConnect--63221883672141
firstReactRender--15117381521
initialActions--2031322
loadScripts--13301106167410113981495
setupStore--146121171261
numNetworkReqs--231287171866
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27101971435851728703822
load--15261207269333316532406
domContentLoaded--15261207269233416532406
domInteractive--12333726129103489
firstPaint--------
backgroundConnect--3531131574326403975
firstReactRender--19153942227
initialActions--103122
loadScripts--14741189251429416172237
setupStore--22751273297392794
numNetworkReqs--66351583089123
19--------
📊 Page Load Benchmark Results

Current Commit: f35f825 | Date: 2/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±38ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 728ms (±37ms) 🟢 | historical mean value: 723ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 78ms (±10ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 38ms 1.01s 1.34s 1.07s 1.34s
domContentLoaded 728ms 37ms 698ms 1.01s 755ms 1.01s
firstPaint 78ms 10ms 64ms 160ms 92ms 160ms
firstContentfulPaint 78ms 10ms 64ms 160ms 92ms 160ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 58 Bytes (0%)
  • ui: 35.44 KiB (0.43%)
  • common: 1.56 KiB (0.02%)

@metamaskbotv2
Copy link
Copy Markdown
Contributor

metamaskbotv2 bot commented Feb 5, 2026

Builds ready [6c0ede6]
UI Startup Metrics (1371 ± 104 ms)
PlatformBuildTypePageMetricTest Title (ms)Persona (ms)Mean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--13711156163610414451546
load--1188977140210312741344
domContentLoaded--1182967137910212681338
domInteractive--2716137202481
firstPaint--163661262164192315
backgroundConnect--23121428812235257
firstReactRender--16103031821
initialActions--107113
loadScripts--966751117410310511115
setupStore--1263151526
numNetworkReqs--231588201582
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--17301358268019517792137
load--11241010190216510981591
domContentLoaded--11111004189316410911571
domInteractive--36181663034130
firstPaint--184711586165221406
backgroundConnect--32028243834334391
firstReactRender--241563102552
initialActions--103112
loadScripts--87577415861538541327
setupStore--1463661725
numNetworkReqs--1225027151144244
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--84566811211149351071
load--7175941032108799923
domContentLoaded--7125911024107794916
domInteractive--251590182278
firstPaint--1056036155115214
backgroundConnect--3317119213382
firstReactRender--14103041527
initialActions--104112
loadScripts--7095891022106789914
setupStore--1163441117
numNetworkReqs--231591211585
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1239892204619613261719
load--72062011151177161067
domContentLoaded--71061511031177091059
domInteractive--3418188263297
firstPaint--149661097155149399
backgroundConnect--16513040558161332
firstReactRender--22163742331
initialActions--104111
loadScripts--70761310951157071050
setupStore--1252131316
numNetworkReqs--1214728552146270
19--------
FirefoxBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--16301324395729817172007
load--13701123376828414421608
domContentLoaded--13691123376128414421608
domInteractive--71322023989148
firstPaint--------
backgroundConnect--71292054189157
firstReactRender--12103941316
initialActions--103112
loadScripts--13321098373928014131582
setupStore--13574121235
numNetworkReqs--2512103231893
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27812049446456832033900
load--15651271254231116652420
domContentLoaded--15641271253631116652420
domInteractive--11635788105125339
firstPaint--------
backgroundConnect--3061151376283298900
firstReactRender--19136892027
initialActions--2011122
loadScripts--15081203251629715422318
setupStore--110872916388574
numNetworkReqs--67401412894122
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--15431326212814615981819
load--13321131164710213841535
domContentLoaded--13311127164710213841534
domInteractive--792820139104152
firstPaint--------
backgroundConnect--59231703477130
firstReactRender--14106151420
initialActions--103112
loadScripts--1300111815859513591476
setupStore--164238281260
numNetworkReqs--231388181876
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27301980680462430233798
load--15791240551549817382269
domContentLoaded--15781240551549817382268
domInteractive--1123273412497509
firstPaint--------
backgroundConnect--32012013862793441047
firstReactRender--22156072334
initialActions--203123
loadScripts--15221218548847716542169
setupStore--1847854236270741
numNetworkReqs--64381392787122
19--------
📊 Page Load Benchmark Results

Current Commit: 6c0ede6 | Date: 2/5/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 970ms (±39ms) 🟢 | historical mean value: 1.03s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 675ms (±36ms) 🟢 | historical mean value: 723ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 74ms (±11ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 970ms 39ms 943ms 1.24s 997ms 1.24s
domContentLoaded 675ms 36ms 653ms 927ms 699ms 927ms
firstPaint 74ms 11ms 60ms 164ms 84ms 164ms
firstContentfulPaint 74ms 11ms 60ms 164ms 84ms 164ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 58 Bytes (0%)
  • ui: 35.5 KiB (0.43%)
  • common: 1.56 KiB (0.02%)

@metamaskbotv2
Copy link
Copy Markdown
Contributor

metamaskbotv2 bot commented Feb 5, 2026

Builds ready [ff23a27]
UI Startup Metrics (1395 ± 96 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup1395118017559614611528
load1202100015029012691322
domContentLoaded119699014939212641317
domInteractive2716114202284
firstPaint158661147120203261
backgroundConnect23421629917236272
firstReactRender17103651926
initialActions108114
loadScripts97876212539310491098
setupStore1363651521
numNetworkReqs231588211584
BrowserifyPower User HomeuiStartup308715379988189837236627
load12551049193816113131556
domContentLoaded12391032193015612951550
domInteractive3819147263798
firstPaint221871765233256322
backgroundConnect9962904677106613393603
firstReactRender24144862534
initialActions104111
loadScripts992813157414110561271
setupStore1564661724
numNetworkReqs983520634116172
WebpackStandard HomeuiStartup89067611801179631092
load7496061082119820985
domContentLoaded7436011074118815978
domInteractive2716113192376
firstPaint1116231352141213
backgroundConnect3718155263994
firstReactRender16103961829
initialActions104112
loadScripts7405991072117811976
setupStore1373851522
numNetworkReqs231589201581
WebpackPower User HomeuiStartup1201905191319012781620
load70159411041196911027
domContentLoaded69158610981206771019
domInteractive3518103203689
firstPaint1506438263189252
backgroundConnect16714151043164236
firstReactRender21163232227
initialActions102011
loadScripts68858410901186751010
setupStore1141831317
numNetworkReqs1454930148164230
FirefoxBrowserifyStandard HomeuiStartup16831374222919417912120
load14251160182414515101715
domContentLoaded14241160182314515101715
domInteractive843718641112150
firstPaint------
backgroundConnect812921649107176
firstReactRender13102831319
initialActions105122
loadScripts13771145172712214341606
setupStore195254311450
numNetworkReqs251298231890
BrowserifyPower User HomeuiStartup27682141649950829753284
load15261292497439315561842
domContentLoaded15261291497439315561842
domInteractive15451674107193345
firstPaint------
backgroundConnect4291131388281611933
firstReactRender18143341926
initialActions203122
loadScripts14811261492239115191811
setupStore16217860195190607
numNetworkReqs944217128112148
WebpackStandard HomeuiStartup15741320236015216431819
load13651159169511014331574
domContentLoaded13641155169511014321573
domInteractive872822341122143
firstPaint------
backgroundConnect63232044087154
firstReactRender13102021417
initialActions107122
loadScripts1328114616699713751486
setupStore155213281138
numNetworkReqs231297171867
WebpackPower User HomeuiStartup28352186824878429143668
load16161230690072516072068
domContentLoaded16151229689972516072068
domInteractive190471747223172543
firstPaint------
backgroundConnect4021111385281529915
firstReactRender20156962328
initialActions102122
loadScripts15751212686572415581998
setupStore14810745151160505
numNetworkReqs89411872899140
📊 Page Load Benchmark Results

Current Commit: ff23a27 | Date: 2/5/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.06s (±61ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 739ms (±59ms) 🟢 | historical mean value: 730ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 78ms (±11ms) 🟢 | historical mean value: 77ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.06s 61ms 1.02s 1.33s 1.26s 1.33s
domContentLoaded 739ms 59ms 708ms 1.01s 941ms 1.01s
firstPaint 78ms 11ms 60ms 176ms 84ms 176ms
firstContentfulPaint 78ms 11ms 60ms 176ms 84ms 176ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 58 Bytes (0%)
  • ui: 36.11 KiB (0.43%)
  • common: 1.55 KiB (0.01%)

@github-project-automation github-project-automation bot moved this to Needs dev review in PR review queue Feb 13, 2026
onClick={() => {
// TODO: Navigate to learn page
}}
onClick={handleLearnPerps}
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.

Missing data-testid for "Learn the basics of perps" buttton.

@geositta geositta added this pull request to the merge queue Feb 14, 2026
@github-project-automation github-project-automation bot moved this from Needs dev review to Review finalised - Ready to be merged in PR review queue Feb 14, 2026
Merged via the queue into main with commit ad881f8 Feb 14, 2026
180 of 181 checks passed
@geositta geositta deleted the perps/learn-perps branch February 14, 2026 05:07
@github-project-automation github-project-automation bot moved this from Review finalised - Ready to be merged to Merged, Closed or Archived in PR review queue Feb 14, 2026
@github-actions github-actions bot locked and limited conversation to collaborators Feb 14, 2026
@metamaskbot metamaskbot added the release-13.20.0 Issue or pull request that will be included in release 13.20.0 label Feb 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.20.0 Issue or pull request that will be included in release 13.20.0 size-XL team-perps Perps team

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants