Skip to content

refactor: migrate onboarding screens to design system with Tailwind CSS (Part 1)#26673

Merged
tylerc-consensys merged 28 commits into
mainfrom
refactor/onboarding-tailwind-migration-part1
Mar 16, 2026
Merged

refactor: migrate onboarding screens to design system with Tailwind CSS (Part 1)#26673
tylerc-consensys merged 28 commits into
mainfrom
refactor/onboarding-tailwind-migration-part1

Conversation

@tylerc-consensys
Copy link
Copy Markdown
Contributor

@tylerc-consensys tylerc-consensys commented Feb 27, 2026

Description

Replace StyleSheet.create() and raw View/Text components with design-system-react-native Box/Text and useTailwind() in Onboarding, OnboardingSheet, OnboardingSuccess, and OnboardingSuccessEndAnimation. Delete the now-unused .styles.ts files.

Part 1 of 2. Part 2 will cover ImportFromSecretRecoveryPhrase and ImportNewSecretRecoveryPhrase.

Changelog

CHANGELOG entry: null

Related issues

Refs: TO-555 - Migrate Onboarding screen to Design System (Box/Text + Tailwind)
Refs: TO-556 - Migrate OnboardingSuccess screen to Design System (Box/Text + Tailwind)
Refs: TO-557 - Migrate OnboardingSuccessEndAnimation to Design System (Box/Text + Tailwind)

Manual testing steps

No functional changes. Visual regression only — verify onboarding screens render correctly.

Feature: Onboarding screens styling

  Scenario: user views onboarding screens
    Given app is freshly installed

    When user launches the app and reaches onboarding
    Then all onboarding screens render identically to before

Screenshots/Recordings

Before (left) vs After (right)

Screenshot 2026-03-04 at 7 02 57 PM Screenshot 2026-03-04 at 7 06 40 PM Screenshot 2026-03-04 at 7 40 13 PM

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.

Made with Cursor


Note

Medium Risk
Mostly a UI refactor, but it touches the app’s onboarding entry screens, loading overlay, and toast timing/padding, so visual/layout regressions or missed edge cases could impact first-run flow.

Overview
Migrates Onboarding, OnboardingSheet, and OnboardingSuccessEndAnimation off StyleSheet/raw View/component-library buttons onto @metamask/design-system-react-native (Box, Button, Text, TextButton) with Tailwind (useTailwind) styling, and removes the now-unused styles.ts files.

Tweaks onboarding toast behavior by tracking the hide setTimeout in a ref and clearing it on unmount, and updates notification bottom padding to explicitly vary for iPhone X vs non–iPhone X.

Expands and updates Jest tests/snapshots to cover medium vs non-medium device spacing/button sizing, loading overlay messaging, iPhone X notification padding, and safe handling when OnboardingSheet route params are undefined.

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

Replace StyleSheet.create() and raw View/Text components with
design-system-react-native Box/Text and useTailwind() in Onboarding,
OnboardingSheet, OnboardingSuccess, and OnboardingSuccessEndAnimation.
Delete the now-unused .styles.ts files.

Made-with: Cursor
@tylerc-consensys tylerc-consensys added no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed team-onboarding Onboarding team labels Feb 27, 2026
@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.

@tylerc-consensys tylerc-consensys marked this pull request as ready for review March 2, 2026 08:46
@tylerc-consensys tylerc-consensys requested a review from a team as a code owner March 2, 2026 08:46
Comment thread app/components/Views/OnboardingSuccess/index.tsx
MMSans-Regular is not registered in the TWRNC config, so
font-["MMSans-Regular"] was silently ignored and the DisplayMD
variant's Geist-Bold took precedence. Pass it via a style object
to tw.style() so the override applies correctly.

Made-with: Cursor
Comment thread app/components/Views/OnboardingSuccess/index.tsx Outdated
Pressable has no built-in opacity change on press unlike
TouchableOpacity. Add a function-style style prop that applies
opacity-60 when pressed to preserve the visual feedback.

Made-with: Cursor
Revert the settings action from Pressable back to TouchableOpacity to preserve the native pressed-state opacity feedback and match previous onboarding behavior.

Made-with: Cursor
Update OnboardingSuccess to accept route props with a default successFlow fallback and sync test/snapshot expectations with current main branch behavior to prevent merge-CI snapshot mismatches.
Resolve OnboardingSheet snapshot conflict by regenerating snapshots from merged code.

Made-with: Cursor
Remove deprecated component-library Text usage from onboarding and onboarding sheet, and update snapshots for the new text component output.

Made-with: Cursor
Comment thread app/components/Views/Onboarding/index.tsx
@tylerc-consensys tylerc-consensys self-assigned this Mar 3, 2026
Cover new onboarding Tailwind migration branches and route fallbacks to satisfy Sonar new-code coverage, and update OnboardingSuccess snapshots to match current design token output.

Made-with: Cursor
Comment thread app/components/Views/Onboarding/index.test.tsx Outdated
Address Cursor bot review comments:
- Add missing variant prop to loading message Text in renderLoader
- Replace toBeTruthy() with toBeOnTheScreen() in loader test assertion

Made-with: Cursor
Comment thread app/components/Views/Onboarding/index.test.tsx
Comment thread app/components/Views/Onboarding/index.test.tsx
…ior tests

Address Cursor Bugbot review feedback by splitting combined tests into
isolated tests that each verify one behavior with specific assertions,
per unit testing guidelines.

Made-with: Cursor
Comment thread app/components/Views/Onboarding/index.tsx Outdated
The showNotification setTimeout was never cleared when the component
unmounted, causing Animated.timing to fire after Jest tears down the
environment and crash CI with exit code 1.

Made-with: Cursor
Comment thread app/components/Views/Onboarding/index.tsx Outdated
Comment thread app/components/Views/OnboardingSheet/index.tsx
Comment thread app/components/Views/OnboardingSheet/index.tsx
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

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.

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

Comment thread app/components/Views/Onboarding/index.tsx
variant={TextVariant.DisplayMd}
fontFamily={FontFamily.Accent}
style={tw.style('mt-[25px] mb-4 mx-4 text-center font-thin')}
>
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.

font-thin is fontWeight 100, but the old code used fontFamily: 'MMSans-Regular' which is regular (400) weight. This looks like a visual regression — please verify against the design spec.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

for this i did manual intervention, previously when matching the design system it produces this: (left old right new), "Your wallet is ready" font is very different

Screenshot 2026-03-04 at 2 46 06 PM

isInverse on ButtonVariant.Secondary introduces a white borderColor.
Add borderColor: 'transparent' via tw.style() to match the old appearance.

Made-with: Cursor
…m migration

- OnboardingSuccess title: use FontWeight.Regular + fontWeight override to
  match old MMSans-Regular appearance (DisplayMd bakes in fontWeight 700)
- OnboardingSheet "or" divider: restore 20px fontSize lost in variant switch
- OnboardingSheet legal text: use FontWeight.Medium to match old Geist-Medium

Made-with: Cursor
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 9, 2026

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeWalletPlatform, SmokeAccounts
  • Selected Performance tags: @PerformanceOnboarding
  • Risk Level: medium
  • AI Confidence: 80%
click to see 🤖 AI reasoning details

E2E Test Selection:
All changes are localized to the Onboarding UI flow (Onboarding, OnboardingSheet, OnboardingSuccess, and related animation/styles/tests). These components are directly involved in wallet creation and first-time user flows.

SmokeWalletPlatform is required because it covers wallet lifecycle events such as new wallet creation and SRP import, which depend on the onboarding flow functioning correctly. Any UI or flow regression here could break wallet creation, analytics tracking, or navigation into the main wallet.

SmokeAccounts is selected as onboarding culminates in account creation tied to the initial SRP. While the PR does not modify account controllers directly, onboarding regressions could impact account initialization and visibility, which are validated under SmokeAccounts.

No changes affect network management, confirmations, trade flows, card, perps, predictions, ramps, multi-chain APIs, or snaps. Therefore, related tags are not required.

Performance Test Selection:
The changes directly modify onboarding screens and success animations, which are part of the first-time user experience measured by onboarding performance tests. UI/layout or animation changes could impact render time and transition performance. No changes were made to app initialization, account list rendering, swaps, asset loading, or other performance-sensitive areas, so only onboarding performance tests are required.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Mar 9, 2026

fontFamily={FontFamily.Accent}
fontWeight={FontWeight.Regular}
style={tw.style('mt-6 mb-4 mx-4 text-center', {
fontWeight: '400',
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.

fontWeight: '400' in the style object is redundant, FontWeight.Regular already resolves that thing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

here's the reply from AI:

However, as we discovered during our earlier debugging, the fontWeight: '400' override is not redundant — it's needed because TextVariant.DisplayMd via twrnc bakes in fontWeight: '700', and the FontWeight.Regular prop alone doesn't override that baked-in value from the Tailwind class. Without the explicit '400' in the style object, the title renders bold instead of matching the old MMSans-Regular appearance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

and also i tested visually, only by applying what suggested by AI it looks 100% the same as before

github-merge-queue Bot pushed a commit that referenced this pull request Mar 9, 2026
…SS (Part 2) (#26736)

## **Description**

Replace StyleSheet.create() and raw View/Text components with
design-system-react-native Box/Text and useTailwind() in
ImportFromSecretRecoveryPhrase and ImportNewSecretRecoveryPhrase. Delete
the now-unused .styles.ts files.

Part 2 of 2. Part 1: #26673

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: [TO-554 - Migrate @MetaMask/web3auth onboarding screens to Design
System with Tailwind
CSS](https://consensyssoftware.atlassian.net/browse/TO-554)

## **Manual testing steps**

No functional changes. Visual regression only — verify import SRP
screens render correctly.

```gherkin
Feature: Import SRP screens styling

  Scenario: user imports wallet using SRP
    Given app is freshly installed

    When user taps "I already have a wallet" and enters SRP
    Then import screens render identically to before
```

## **Screenshots/Recordings**

### **Before left, after right**
<img width="500" height="1066" alt="Screenshot 2026-03-02 at 11 16
46 AM"
src="https://github.com/user-attachments/assets/4ef5ca42-5c71-42d2-b16e-5bbd8ec77f16"
/>
<img width="500" height="1059" alt="Screenshot 2026-03-02 at 11 16
59 AM"
src="https://github.com/user-attachments/assets/3e8b276e-937e-429d-b962-ecbc3b001bbb"
/>


## **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.

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily a UI refactor, but it touches the wallet import/onboarding
SRP flows where styling/layout regressions could block users or break
keyboard/safe-area behavior across iOS/Android.
> 
> **Overview**
> Migrates `ImportFromSecretRecoveryPhrase` and
`ImportNewSecretRecoveryPhrase` from `StyleSheet.create()` and raw
`View`/library `Text` components to design-system `Box`/`Text`/`Label`
with `useTailwind()` styling, including minor platform-specific spacing
tweaks.
> 
> Deletes the now-unused `styles.ts` files and updates the Jest snapshot
to reflect the new component/styling output.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2c5e19c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
grvgoel81
grvgoel81 previously approved these changes Mar 10, 2026
@tylerc-consensys tylerc-consensys added this pull request to the merge queue Mar 10, 2026
@grvgoel81 grvgoel81 removed this pull request from the merge queue due to a manual request Mar 10, 2026
The design system ButtonSecondary hardcodes numberOfLines: 1 and
ButtonBase uses a fixed h-12, so long strings like "Import using
Secret Recovery Phrase" get clipped on narrower devices.

Override with min-h-12 h-auto py-3 and numberOfLines: 0 so the
button expands to fit its content.

Made-with: Cursor
Same numberOfLines: 1 and fixed-height issue as OnboardingSheet.
Apply min-h h-auto py-3 and numberOfLines: 0 to both "Create a
new wallet" and "I have an existing wallet" buttons.

Made-with: Cursor
@github-actions
Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
8 value mismatches detected (expected — fixture represents an existing user).
View details

## **Description**

Users who set their system font size to maximum scale experience button
text clipping on the Onboarding and OnboardingSheet screens. The design
system `ButtonPrimary` and `ButtonSecondary` both hardcode
`numberOfLines: 1` with `ellipsizeMode: 'clip'`, and `ButtonBase` uses a
fixed height (`h-12` for Lg, `h-10` for Md). This means longer strings
like "Import using Secret Recovery Phrase" and "I have an existing
wallet" get cut off instead of wrapping.

This fix overrides the button containers to use `min-h h-auto py-3` and
sets `numberOfLines: 0` so buttons expand to fit their content at any
font scale.

> **Depends on** #26673 being merged first — this branch is based on
`refactor/onboarding-tailwind-migration-part1`.

### Screens fixed

| Screen | Buttons |
|--------|---------|
| `Onboarding/index.tsx` | "Create a new wallet", "I have an existing
wallet" |
| `OnboardingSheet/index.tsx` | "Import using Secret Recovery Phrase" /
"Continue with Secret Recovery Phrase" |

### Root cause

Two constraints in `@metamask/design-system-react-native`:
1. `ButtonPrimary` and `ButtonSecondary` both pass `numberOfLines: 1,
ellipsizeMode: 'clip'` to `ButtonBase` text props
2. `ButtonBase` applies a fixed height class (`h-12` for Lg, `h-10` for
Md) via `TWCLASSMAP_BUTTONBASE_SIZE_DIMENSION`

Both are overridable from the consumer side via `textProps` and
`twClassName`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Depends on: #26673

## **Manual testing steps**

```gherkin
Feature: Onboarding button text wrapping at max font scale

  Scenario: user views onboarding with system font set to maximum
    Given app is freshly installed
    And user's system font size is set to largest/maximum

    When user reaches the onboarding screen
    Then "Create a new wallet" and "I have an existing wallet" buttons display full text without clipping

  Scenario: user views onboarding sheet with large font
    Given user taps "Create a new wallet" or "I already have a wallet"

    When the onboarding sheet appears
    Then the "Import using Secret Recovery Phrase" button text wraps to multiple lines instead of being clipped
```

## **Screenshots/Recordings**

### **Before**

Button text is clipped to one line on devices with max font scale:

<img width="300" height="1280" alt="Screenshot_1773224200"
src="https://github.com/user-attachments/assets/855a3bad-c6b7-4f1a-8341-3f513ad0ebde"
/>

<img width="300" alt="Screenshot_1773222833"
src="https://github.com/user-attachments/assets/2dccc4cd-5a4f-4ed9-bf8b-1246b2f17136"
/>

### **After**

Buttons expand to fit the full text:

<img width="300" height="1280" alt="Screenshot_1773224472"
src="https://github.com/user-attachments/assets/41930a9c-bfca-4b7c-a10c-bd32cc388a1c"
/>

<img width="300" alt="Screenshot_1773222827"
src="https://github.com/user-attachments/assets/6dc37a93-4fbc-4797-ad9f-809537465e82"
/>

## **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.
@tylerc-consensys tylerc-consensys added this pull request to the merge queue Mar 16, 2026
Merged via the queue into main with commit 477da9e Mar 16, 2026
6 of 7 checks passed
@tylerc-consensys tylerc-consensys deleted the refactor/onboarding-tailwind-migration-part1 branch March 16, 2026 10:55
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 16, 2026
@metamaskbot metamaskbot added the release-7.71.0 Issue or pull request that will be included in release 7.71.0 label Mar 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed release-7.71.0 Issue or pull request that will be included in release 7.71.0 size-L team-onboarding Onboarding team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants