Skip to content

fix(ramps): fix Transak checkout background color mismatch — native flow (TMCU-1087)#33310

Closed
georgewrmarshall wants to merge 6 commits into
mainfrom
cursor/transak-checkout-pure-black-1087-4851
Closed

fix(ramps): fix Transak checkout background color mismatch — native flow (TMCU-1087)#33310
georgewrmarshall wants to merge 6 commits into
mainfrom
cursor/transak-checkout-pure-black-1087-4851

Conversation

@georgewrmarshall

@georgewrmarshall georgewrmarshall commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes the Transak checkout BottomSheet background color mismatch in the native unified buy flow (app/components/UI/Ramp/Views/Checkout/). This was a pre-existing issue that became more visible after the pure-black BottomSheet change.

The fix overrides the BottomSheet (twClassName) and WebView (backgroundColor) to match Transak's iframe theme colors (#1a1a1a dark / #ffffff light), sourced from new constants in app/styles/common.ts, so the native chrome is seamless with the embedded checkout.

The ScreenLayout wrapper was also removed from the error state — it was painting colors.background.default over the BottomSheet surface, causing a mismatch in pure-black mode. And ErrorView's own hardcoded background has been removed so the container (BottomSheet or ScreenLayout) is always responsible for the surface color.

Note: The equivalent fix for the legacy aggregator flow (app/components/UI/Ramp/Aggregator/Views/Checkout/) will be done in a follow-up PR.

Changelog

CHANGELOG entry: null

Related issues

Fixes: TMCU-1087

Manual testing steps

Feature: Transak checkout background color

  Scenario: user opens Transak checkout in dark mode
    Given the app is in dark mode
    And the user has selected a Transak Buy quote

    When user proceeds to the checkout screen
    Then the BottomSheet background matches the Transak iframe background with no visible color mismatch

  Scenario: user opens Transak checkout in light mode
    Given the app is in light mode
    And the user has selected a Transak Buy quote

    When user proceeds to the checkout screen
    Then the BottomSheet background is white matching the Transak iframe background

Screenshots/Recordings

Before

Simulator Screenshot - iPhone 17 Pro Max - 2026-07-15 at 18 58 49

After

Simulator Screenshot - iPhone 17 Pro - 2026-07-15 at 19 01 11Simulator Screenshot - iPhone 17 Pro - 2026-07-15 at 19 25 59

Before

beforeios.mov

After

iOS

afterios.mov

Android

androidafter.mov

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • 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.

@metamask-ci metamask-ci Bot added team-design-system All issues relating to design system in Mobile INVALID-PR-TEMPLATE PR's body doesn't match template labels Jul 15, 2026
@metamask-ci

metamask-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

PR template — items to address before "Ready for review"

Warnings — informational, address before merging:

  • Pre-merge author checklist has unchecked items (e.g. "I've applied the right labels on the PR (see labeling guidelines). Not required for external contributors."). Every box must be consciously checked — see docs/readme/ready-for-review.md.

See docs/readme/ready-for-review.md for the full Definition of Ready for Review.

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🧪 Flaky unit test detection

✅ All previously detected unit test flakiness issues in this PR have been fixed.

View recent run history

This check is informational only and does not block merging.

@georgewrmarshall georgewrmarshall self-assigned this Jul 15, 2026
…t (TMCU-1087)

Use getElevatedSurfaceColor for Checkout WebView chrome so pure-black dark
mode uses bg-alternative and light mode uses bg-default, matching MMDS
BottomSheet elevated surfaces.

When pure black is enabled, append Transak widget theme params to the buy
URL before fetching the provider widget so the hosted checkout background
matches the in-app sheet instead of Transak's default charcoal.

Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com>
@georgewrmarshall
georgewrmarshall force-pushed the cursor/transak-checkout-pure-black-1087-4851 branch from c533290 to 39922f2 Compare July 15, 2026 21:34
Set BottomSheet and WebView background to Transak-specific colors
(#1a1a1a dark / #ffffff light) so the sheet matches the iframe content
and eliminates the visible color mismatch on open.
@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.

@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 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Transak hex ignores pure black
    • Replaced Transak hex backgrounds with getElevatedSurfaceColor/useElevatedSurface to respect pure black and match the widget.
  • ✅ Fixed: Error sheet missing background class
    • Added twClassName={transakBgClassName} to the error BottomSheet for consistent background styling.

Create PR

Or push these changes by commenting:

@cursor push 1b97efb146
Preview (1b97efb146)
diff --git a/app/components/UI/Ramp/Views/Checkout/Checkout.styles.ts b/app/components/UI/Ramp/Views/Checkout/Checkout.styles.ts
--- a/app/components/UI/Ramp/Views/Checkout/Checkout.styles.ts
+++ b/app/components/UI/Ramp/Views/Checkout/Checkout.styles.ts
@@ -1,19 +1,15 @@
 import { StyleSheet } from 'react-native';
-import { Theme, AppThemeKey } from '../../../../../util/theme/models';
-import { colors } from '../../../../../styles/common';
+import { Theme } from '../../../../../util/theme/models';
+import { getElevatedSurfaceColor } from '../../../../../util/theme/themeUtils';
 
-const styleSheet = (params: { theme: Theme }) => {
-  const isDark = params.theme.themeAppearance === AppThemeKey.dark;
-  return StyleSheet.create({
+const styleSheet = (params: { theme: Theme }) =>
+  StyleSheet.create({
     headerWithoutPadding: {
       paddingVertical: 0,
     },
     webview: {
-      backgroundColor: isDark
-        ? colors.transakBackgroundDark
-        : colors.transakBackgroundLight,
+      backgroundColor: getElevatedSurfaceColor(params.theme),
     },
   });
-};
 
 export default styleSheet;

diff --git a/app/components/UI/Ramp/Views/Checkout/Checkout.tsx b/app/components/UI/Ramp/Views/Checkout/Checkout.tsx
--- a/app/components/UI/Ramp/Views/Checkout/Checkout.tsx
+++ b/app/components/UI/Ramp/Views/Checkout/Checkout.tsx
@@ -44,9 +44,7 @@
 } from '../../headless/headlessEntryNavigation';
 import { useStyles } from '../../../../hooks/useStyles';
 import styleSheet from './Checkout.styles';
-import { useTheme } from '../../../../../util/theme';
-import { AppThemeKey } from '../../../../../util/theme/models';
-import { colors } from '../../../../../styles/common';
+import { useElevatedSurface } from '../../../../../util/theme/themeUtils';
 import Device from '../../../../../util/device';
 import { shouldStartLoadWithRequest } from '../../../../../util/browser';
 import { CHECKOUT_TEST_IDS } from './Checkout.testIds';
@@ -102,11 +100,7 @@
   const navigation = useNavigation();
   const params = useParams<CheckoutParams>();
   const { styles } = useStyles(styleSheet, {});
-  const { themeAppearance } = useTheme();
-  const transakBgClassName =
-    themeAppearance === AppThemeKey.dark
-      ? `bg-[${colors.transakBackgroundDark}]`
-      : `bg-[${colors.transakBackgroundLight}]`;
+  const transakBgClassName = useElevatedSurface();
   const { addOrder, addPrecreatedOrder, getOrderFromCallback } =
     useRampsOrders();
   const { trackEvent, createEventBuilder } = useAnalytics();
@@ -669,6 +663,7 @@
         goBack={navigation.goBack}
         isFullscreen
         keyboardAvoidingViewEnabled={false}
+        twClassName={transakBgClassName}
       >
         {sharedHeader}
         <ScreenLayout>

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit abb86f3. Configure here.

Comment thread app/components/UI/Ramp/Views/Checkout/Checkout.styles.ts
Comment thread app/components/UI/Ramp/Views/Checkout/Checkout.tsx
@georgewrmarshall georgewrmarshall changed the title fix(ramps): align Transak checkout WebView with pure-black BottomSheet (TMCU-1087) fix(ramps): fix Transak checkout background color mismatch (TMCU-1087) Jul 15, 2026
@metamask-ci metamask-ci Bot removed the INVALID-PR-TEMPLATE PR's body doesn't match template label Jul 15, 2026
…eckout

The ScreenLayout component has a hardcoded backgroundColor that was
overriding the BottomSheet background, causing a white/grey flash in
the error state of the Transak checkout flow.
@github-actions github-actions Bot added size-S and removed size-M labels Jul 16, 2026
The ErrorView component was setting backgroundColor: colors.background.default
on its screen wrapper, which conflicted with the BottomSheet container
background (especially in pure-black mode where the sheet uses bg-alternative).
The container is always responsible for the surface color, so ErrorView
should be transparent and inherit from its parent.
@github-actions

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: 92%
click to see 🤖 AI reasoning details

E2E Test Selection:
The PR makes targeted UI/styling changes to the Ramp (fiat on-ramp) Checkout flow:

  1. Checkout.tsx: Adds theme-aware Transak background color to the BottomSheet via twClassName, and simplifies the error state by removing the ScreenLayout wrapper around ErrorView.
  2. Checkout.styles.ts: Updates WebView background to use Transak-specific colors (dark/light) instead of the design system default.
  3. ErrorView.tsx: Removes backgroundColor from the container style (now handled at BottomSheet level).
  4. app/styles/common.ts: Adds two new color constants (transakBackgroundDark, transakBackgroundLight) — purely additive, no existing values changed.

All changes are scoped to the Ramp/Checkout UI and affect only the visual appearance of the Transak checkout flow. No functional logic, navigation, or shared infrastructure is modified. The app/styles/common.ts change is purely additive (new constants only), so no risk of breaking other components.

SmokeMoney is the appropriate tag as it covers MetaMask Card and fiat on/off-ramp (ramps) flows, including the checkout experience. No other tags are needed since:

  • No confirmation flows are changed (no transaction logic)
  • No swap flows are changed
  • No shared navigation/modal infrastructure is affected
  • The ErrorView change is a layout simplification within the Ramp context only

Performance Test Selection:
The changes are purely UI/styling adjustments to the Ramp Checkout flow — adding Transak-specific background colors and simplifying the error view layout. There are no changes to data fetching, rendering loops, asset loading, or any performance-sensitive code paths. No performance test tags are warranted.

View GitHub Actions results

backgroundColor: params.theme.colors.background.default,
backgroundColor: isDark
? colors.transakBackgroundDark
: colors.transakBackgroundLight,

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.

Both the BottomSheet (twClassName) and the WebView (style.backgroundColor) need the same color for different reasons: twClassName sets the container surface so the native chrome matches the iframe, while the WebView background prevents a momentary flash of white or transparent content before Transak's page finishes loading. Centralising both in colors.transak* ensures they always agree.

isInteractable={!Device.isAndroid()}
keyboardAvoidingViewEnabled={false}
twClassName={transakBgClassName}
>

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.

Only the WebView BottomSheet gets the Transak background override — the error state intentionally keeps the default design-system surface (bg-alternative in pure-black, bg-default otherwise). Applying it to the error state would make MetaMask's own error UI appear on a non-standard background with no benefit.

setError('');
isRedirectionHandledRef.current = false;
lastLoadCompleteUrlRef.current = null;
loadUrlErrorsRef.current.clear();

@georgewrmarshall georgewrmarshall Jul 16, 2026

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.

ScreenLayout seems more appropriate for pages and set backgroundColor: colors.background.default on its container, which overrode the BottomSheet's surface color and made the error state appear on the wrong background in pure-black mode. Rendering ErrorView directly inside BottomSheet lets the sheet's own surface show through correctly.

Before / After

ImageImage

@@ -28,7 +28,6 @@ const createStyles = (
flex: options?.asScreen ? 1 : undefined,
justifyContent: 'center',

@georgewrmarshall georgewrmarshall Jul 16, 2026

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.

Every call site renders ErrorView inside a container that already owns the surface color — either a BottomSheet or a ScreenLayout. Having ErrorView also paint a background caused a visual conflict in pure-black mode where the container surface (bg-alternative) differed from colors.background.default. Making the component transparent keeps the responsibility with the container.

Before / After

ImageImage

@georgewrmarshall georgewrmarshall changed the title fix(ramps): fix Transak checkout background color mismatch (TMCU-1087) fix(ramps): fix Transak checkout background color mismatch — native flow (TMCU-1087) Jul 16, 2026
Comment thread app/styles/common.ts
// and outside our control. Used to match the BottomSheet surface so the
// checkout feels seamless. Update only if Transak changes their theme colors.
transakBackgroundDark: '#1a1a1a',
transakBackgroundLight: '#ffffff',

@georgewrmarshall georgewrmarshall Jul 16, 2026

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.

Admittedly I used the eye droper to get the dark color but it seems to match perfectly 😅

Light / Dark

ImageImage

@georgewrmarshall
georgewrmarshall marked this pull request as ready for review July 16, 2026 02:30
@georgewrmarshall
georgewrmarshall requested a review from a team as a code owner July 16, 2026 02:30
@github-actions github-actions Bot added the risk:low AI analysis: low risk label Jul 16, 2026
@sonarqubecloud

Copy link
Copy Markdown

@georgewrmarshall

Copy link
Copy Markdown
Contributor Author

Closing in favor of #33429

auto-merge was automatically disabled July 16, 2026 22:27

Pull request was closed

@github-actions github-actions Bot locked and limited conversation to collaborators Jul 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

risk:low AI analysis: low risk size-S team-design-system All issues relating to design system in Mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants