Skip to content

fix: Polish React Native Toast background, description color and border radius - #1391

Merged
brianacnguyen merged 2 commits into
mainfrom
polish/toast-style
Jul 21, 2026
Merged

fix: Polish React Native Toast background, description color and border radius#1391
brianacnguyen merged 2 commits into
mainfrom
polish/toast-style

Conversation

@amandaye0h

@amandaye0h amandaye0h commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

Polish React Native Toast surface styling so it matches the intended light/dark treatment.

Why: Toast was always using section background, 12px radius, and default description color, which didn’t match the desired visual spec.

What changed:

  • Light theme: background.default + medium shadow
  • Dark theme: background.section (no shadow)
  • Description defaults to TextColor.TextAlternative
  • Border radius updated from 12px (rounded-xl) to 16px (rounded-2xl)
  • Included unit tests for theme background/shadow, radius, and description color

Related issues

Fixes:

#1304
MetaMask/metamask-mobile#32933

Manual testing steps

  1. Run yarn storybook:ios (or Android) and open Components → Toast
  2. In light theme, confirm toast uses default background, medium shadow, and 16px corners
  3. In dark theme, confirm toast uses section background with no shadow
  4. Confirm description text uses the alternative text color
  5. Spot-check Default, severity, action button, and close stories still behave as before

Screenshots/Recordings

Before

Screen.Recording.2026-07-21.at.4.29.10.PM.mov

After

Screen.Recording.2026-07-21.at.4.17.55.PM.mov

Pre-merge author checklist

  • I've followed MetaMask Contributor Docs
  • I've completed the PR template to the best of my ability
  • I’ve included tests if applicable
  • I’ve documented my code using JSDoc format if applicable

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

Co-authored-by: Cursor <cursoragent@cursor.com>
@amandaye0h
amandaye0h requested a review from a team as a code owner July 21, 2026 08:21
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Links

Compare the preview for this pull request with the latest Storybooks from the main branch.

🔀 Pull Request Preview

🌳 Main Branch (Latest)

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Links

Compare the preview for this pull request with the latest Storybooks from the main branch.

🔀 Pull Request Preview

🌳 Main Branch (Latest)

@amandaye0h amandaye0h changed the title fix: Polish Toast background, description color and border radius fix: Polish React Native Toast background, description color and border radius Jul 21, 2026
@brianacnguyen
brianacnguyen merged commit f8c7047 into main Jul 21, 2026
31 checks passed
@brianacnguyen
brianacnguyen deleted the polish/toast-style branch July 21, 2026 15:14
@georgewrmarshall

Copy link
Copy Markdown
Contributor

Follow-up: descriptionProps should be merged in JSX, not defaulted in destructure

We don't use default parameter values for props objects — the convention is to spread defaults inline in the JSX so consumer-provided values can override rather than replace:

// ❌ Current — any consumer-passed `descriptionProps` silently drops the color default
descriptionProps = { color: TextColor.TextAlternative },

// ✅ Preferred — merge in JSX so consumers can still override individual keys
descriptionProps={{ color: TextColor.TextAlternative, ...descriptionProps }}

As-is, passing descriptionProps={{ numberOfLines: 2 }} causes the TextAlternative color to be silently lost. Worth a quick follow-up fix.

@georgewrmarshall

Copy link
Copy Markdown
Contributor

@brianacnguyen — do we have shadow utility classes in the twrnc preset (e.g. shadow-md)? The current impl reaches directly into lightTheme.shadows.size.md from @metamask/design-tokens as an inline style object rather than going through the preset.

If twrnc shadow classes don't exist yet, this is a good candidate to add them to @metamask/design-system-twrnc-preset so shadows stay consistent with the rest of our token-based styling approach and don't require direct @metamask/design-tokens imports in components.

@brianacnguyen

Copy link
Copy Markdown
Contributor

@brianacnguyen — do we have shadow utility classes in the twrnc preset (e.g. shadow-md)? The current impl reaches directly into lightTheme.shadows.size.md from @metamask/design-tokens as an inline style object rather than going through the preset.

If twrnc shadow classes don't exist yet, this is a good candidate to add them to @metamask/design-system-twrnc-preset so shadows stay consistent with the rest of our token-based styling approach and don't require direct @metamask/design-tokens imports in components.

Nope we don't have shadow utilities yet. Agreeing that they’re a good candidate to add

amandaye0h added a commit that referenced this pull request Jul 21, 2026
## **Description**

Follow-up to
[#1391](#1391)
(Toast polish: background, description color, border radius).

### **What issues does this PR address?**

* **`descriptionProps` defaults replace instead of merge**: In
[#1391](#1391),
Toast defaulted `descriptionProps` in the destructure (`descriptionProps
= { color: TextColor.TextAlternative }`). Passing any consumer object
(e.g. `{ numberOfLines: 2 }` or `{ testID: '...' }`) replaced the whole
default, so `TextAlternative` was silently dropped.

### **Key improvements**

* Merge the default description color inline in JSX:
`descriptionProps={{ color: TextColor.TextAlternative,
...descriptionProps }}`, matching the team convention for props objects.
* Add a regression test that passes partial `descriptionProps` and
asserts the default color is still applied.

### **Notes for reviewers**

- Addresses George’s post-merge follow-up on
[#1391](#1391):
merge `descriptionProps` in JSX instead of defaulting in the
destructure.

## **Related issues**

Follow-up to:
#1391

## **Manual testing steps**

1. Open React Native Storybook (`yarn storybook:ios` or `yarn
storybook:android`) and navigate to Toast stories.
2. Confirm description text still uses the alternative text color by
default.
3. Optionally verify a toast with `descriptionProps={{ testID: '...' }}`
(or `numberOfLines`) keeps the alternative color.

## **Screenshots/Recordings**

### **Before**

N/A — behavior fix; visual default is unchanged when `descriptionProps`
is omitted

### **After**

N/A — behavior fix; visual default is unchanged when `descriptionProps`
is omitted

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [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

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

Co-authored-by: Cursor <cursoragent@cursor.com>
@amandaye0h amandaye0h mentioned this pull request Jul 21, 2026
16 tasks
georgewrmarshall pushed a commit that referenced this pull request Jul 22, 2026
<!--
Release PR Template

Use this template for release PRs by creating your PR with:

https://github.com/MetaMask/metamask-design-system/compare/main...release/VERSION?template=release.md

Or use the default PR template and manually copy this structure.
-->

## Release 55.0.0

React Native Toast moves to iOS-style top placement with spring motion,
related offset/padding renames, and surface polish (theme background,
description color, border radius).

### 📦 Package Versions

- `@metamask/design-system-react-native`: **0.37.0**

### 📱 React Native Updates (0.37.0)

#### Changed

- **BREAKING:** Updated `Toast` / `Toaster` to slide in from the top of
the screen (below the safe area) with spring-based enter/exit motion
([#1304](#1304))
  - Renamed `bottomOffset` and `customTopOffset` to `topOffset`
- Renamed exported `TOAST_BOTTOM_PADDING` to `TOAST_TOP_PADDING`
(default padding 36 → 8)
- Migration: [Toast topOffset
renames](./packages/design-system-react-native/MIGRATION.md#toast-bottomoffset-to-topoffset)
- Updated `Toast` surface styling for light/dark themes: light uses
`background.default` with medium shadow; dark uses `background.section`
with no shadow; border radius 12px → 16px; description defaults to
`TextColor.TextAlternative`
([#1391](#1391))

#### Fixed

- Fixed `Toast` `descriptionProps` so partial consumer props merge with
the default `TextAlternative` color instead of replacing it
([#1396](#1396))

### ⚠️ Breaking Changes

#### Toast top placement and offset renames (React Native Only)

**What Changed:**

- Toasts now appear from the **top** of the screen (below the safe area)
instead of the bottom
- `bottomOffset` / `customTopOffset` → `topOffset`
- `TOAST_BOTTOM_PADDING` → `TOAST_TOP_PADDING` (default 36 → 8)

**Migration:**

```tsx
// Before (0.36.0)
import {
  TOAST_BOTTOM_PADDING,
  toast,
} from '@metamask/design-system-react-native';

toast({
  hasNoTimeout: false,
  title: 'Saved',
  bottomOffset: 24,
});

const padding = TOAST_BOTTOM_PADDING;

// After (0.37.0)
import { TOAST_TOP_PADDING, toast } from '@metamask/design-system-react-native';

toast({
  hasNoTimeout: false,
  title: 'Saved',
  topOffset: 24,
});

const padding = TOAST_TOP_PADDING;
```

**Impact:**

- Call sites using `bottomOffset`, `customTopOffset`, or
`TOAST_BOTTOM_PADDING` must rename and re-evaluate numeric offsets tuned
for bottom placement

See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0360-to-0370)

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-system-react-native: minor (0.36.0 → 0.37.0) - Toast top
placement feature + breaking offset/padding renames
- [x] Breaking changes documented with migration guidance
- [x] Migration guides updated with before/after examples (if breaking
changes)
- [x] PR references included in changelog entries

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've reviewed the [Release
Workflow](./.cursor/rules/release-workflow.md) cursor rule
- [x] All tests pass (`yarn build && yarn test && yarn lint`)
- [x] Changelog validation passes (`yarn changelog:validate`)

## **Pre-merge reviewer checklist**

- [ ] I've reviewed the [Reviewing Release
PRs](./docs/reviewing-release-prs.md) guide
- [ ] Package versions follow semantic versioning
- [ ] Changelog entries are consumer-facing (not commit message
regurgitation)
- [ ] Breaking changes are documented in MIGRATION.md with examples
- [ ] All unreleased changes are accounted for in changelogs

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
georgewrmarshall pushed a commit that referenced this pull request Jul 22, 2026
## **Description**

Polishes React Native `BannerBase` spacing so padding and
title/description gap match design more closely.

1. **Bottom padding:** When an action button is below content, use
`paddingBottom={4}` (16px); otherwise keep `3` (12px).
2. **Right padding:** When a close button is present, use
`paddingRight={2}` (8px); otherwise keep `4` (16px).
3. **Title → description gap:** When both are present, add `mt-0.5`
(2px) above the description.

### Impacted components

* `BannerAlert`
* `Toast`

## **Related issues**

Fixes:
#1304
#1391
#1394

## **Manual testing steps**

1. Run `yarn storybook:ios` (or Android) and open **BannerBase** /
**BannerAlert** / **Toast** stories (they compose `BannerBase`).
2. Confirm default padding: 12px vertical, 16px horizontal when there is
no close button and no below action button.
3. With a close button: right padding is 8px.
4. With an action button in `Below` layout: bottom padding is 16px.
5. With title + description: 2px gap between them; description-only has
no extra top margin.

## **Screenshots/Recordings**

### **Before**



https://github.com/user-attachments/assets/070f0754-9b52-45a7-b543-988e10ebbd6f



### **After**



https://github.com/user-attachments/assets/02764783-f984-4e4b-9f02-ba9e18206eca



## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable

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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants