Skip to content

feat: new Toast API design#1104

Merged
georgewrmarshall merged 7 commits into
mainfrom
feat/toast-new-api
Apr 30, 2026
Merged

feat: new Toast API design#1104
georgewrmarshall merged 7 commits into
mainfrom
feat/toast-new-api

Conversation

@kirillzyusko

@kirillzyusko kirillzyusko commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

Description

Introduce new Toast API design. It helps to move even more code into DSRN package and simplify mobile codebase 😎

This PR also includes migration docs.

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-279

Manual testing steps

  1. Go to migration file
  2. Check docs

Screenshots/Recordings

Before

After

image

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
  • I’ve applied the right labels on the PR (see labeling guidelines). 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.

Note

Medium Risk
Medium risk because this is a breaking API change to a shared UI primitive; consumers must mount <Toast /> once and update all call sites to the new static methods or they will throw at runtime.

Overview
Redesigns Toast to use a global static API: the component now registers itself on mount and exposes Toast.show(options) / Toast.hide() so callers no longer need refs, context, or a service singleton.

Removes ToastContext, ToastContextWrapper, and the ToastContextParams type from exports; factors the original rendering/animation logic into a new internal ToastView and adds explicit runtime errors when static methods are called before <Toast /> is mounted.

Updates Storybook, tests, and docs/migration guide to reflect the new “single root mount + static calls anywhere” usage pattern (while keeping forwarded ref methods for advanced/isolated cases).

Reviewed by Cursor Bugbot for commit cc1a7ba. Bugbot is set up for automated code reviews on this repo. Configure here.

@kirillzyusko kirillzyusko self-assigned this Apr 23, 2026
@kirillzyusko kirillzyusko added enhancement New feature or request react-native labels Apr 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@kirillzyusko kirillzyusko marked this pull request as ready for review April 23, 2026 14:34
@kirillzyusko kirillzyusko requested a review from a team as a code owner April 23, 2026 14:34
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall 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.

Really nice work! I think we can merge and make some follow ups to align design and code before releasing in next release

@georgewrmarshall georgewrmarshall enabled auto-merge (squash) April 30, 2026 21:02
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall merged commit d4c9236 into main Apr 30, 2026
44 checks passed
@georgewrmarshall georgewrmarshall deleted the feat/toast-new-api branch April 30, 2026 21:11
georgewrmarshall added a commit that referenced this pull request May 5, 2026
## Release 38.0.0

This release updates the shared, web, native, tokens, and Tailwind
packages with new cross-platform input and avatar-group contracts, new
modal building blocks for React, a breaking React Native Toast API
redesign, and Tailwind CSS v4 support for web consumers.

### 📦 Package Versions

- `@metamask/design-system-shared`: **0.16.0**
- `@metamask/design-system-react`: **0.21.0**
- `@metamask/design-system-react-native`: **0.23.0**
- `@metamask/design-system-tailwind-preset`: **0.7.0**
- `@metamask/design-tokens`: **8.4.0**

### 🔄 Shared Type Updates (0.16.0)

#### Input and AvatarGroup shared contracts
([#1043](#1043),
[#1067](#1067))

**What Changed:**

- Added shared `Input` contracts for controlled `value`, `isReadOnly`,
and `isStateStylesDisabled`
- Added shared `AvatarGroup` size, variant, and prop contracts
- Added the shared `Merge` icon export
([#1155](#1155))

**Impact:**

- React and React Native consumers can build against one aligned input
and avatar-group API surface
- Cross-platform wrappers can depend on `@metamask/design-system-shared`
instead of maintaining platform-specific type assumptions

### 🌐 React Web Updates (0.21.0)

#### Added

- Added `ModalOverlay`, `ModalBody`, `ModalFocus`, and `ModalFooter` to
support Extension modal migrations into `@metamask/design-system-react`
([#1120](#1120),
[#1121](#1121),
[#1128](#1128),
[#1132](#1132))
- Added the `Merge` icon to the React icon set
([#1155](#1155))

#### Changed

- Updated `Input` to follow the shared controlled input API and use
`isReadOnly` as the public readonly prop name
([#1043](#1043))
- Updated `AvatarGroup` to use shared cross-platform size and variant
contracts
([#1067](#1067))

### 📱 React Native Updates (0.23.0)

#### Added

- Added the `Merge` icon to the React Native icon set
([#1155](#1155))

#### Changed

- **BREAKING:** Redesigned `Toast` to use a single mounted `<Toast />`
plus static `Toast.show(...)` and `Toast.hide()` methods for application
usage
([#1104](#1104))
- Removed `ToastContext`, `ToastContextWrapper`, and
`ToastContextParams` from the public export surface
- Renamed `ToastVariants` to `ToastVariant`, changed icon-only close
buttons to `ToastCloseButtonVariant.Icon`, and renamed
`customBottomOffset` to `bottomOffset`
- `Toast.show()` and `Toast.hide()` now throw a descriptive error if
called before `<Toast />` mounts
- See the [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0220-to-0230)
- Updated `Input` to follow the shared controlled input API and rename
`isReadonly` to `isReadOnly`
([#1043](#1043))
- Updated `AvatarGroup` to use shared cross-platform size and variant
contracts
([#1067](#1067))

### 🎨 Tokens and Tailwind Updates

#### `@metamask/design-tokens` 8.4.0

- Added `@metamask/design-tokens/tailwind/theme.css` for Tailwind CSS v4
consumers, providing a single import for token variables, theme values,
typography, fonts, and shadow utilities
([#1117](#1117))

#### `@metamask/design-system-tailwind-preset` 0.7.0

- Added a `fade-in` animation utility so consumers can use
`animate-fade-in` for simple opacity entrance transitions, including the
new `ModalOverlay` web migration path
([#1120](#1120))
- Clarified that Tailwind CSS v3 consumers should keep using this
preset, while Tailwind CSS v4 consumers should migrate to
`@metamask/design-tokens/tailwind/theme.css`
([#1117](#1117))

### ⚠️ Breaking Changes

#### Toast API redesign (React Native)

**What Changed:**

- `Toast` application usage moved from context/service patterns to
static `Toast.show(...)` and `Toast.hide()` methods
- `ToastContext`, `ToastContextWrapper`, and `ToastContextParams` were
removed from the public API
- `ToastVariants` was renamed to `ToastVariant`
- Icon-only close buttons now use `ToastCloseButtonVariant.Icon`
- `customBottomOffset` was renamed to `bottomOffset`

**Impact:**

- Existing `@metamask/design-system-react-native` consumers using the
old Toast context flow need import, root-mount, and call-site updates
- Existing app code must ensure `<Toast />` is mounted before invoking
`Toast.show()` / `Toast.hide()`

See migration guides for complete instructions:

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

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn workspace <package>
changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-system-shared: minor (`0.15.0` → `0.16.0`) - new shared
`Input`, `AvatarGroup`, and icon exports
- [x] design-system-react: minor (`0.20.0` → `0.21.0`) - new modal
components, icon, and shared API alignment
- [x] design-system-react-native: minor (`0.22.0` → `0.23.0`) - breaking
Toast redesign, icon, and shared API alignment
- [x] design-system-tailwind-preset: minor (`0.6.1` → `0.7.0`) - new
`fade-in` utility and Tailwind CSS v4 migration guidance
- [x] design-tokens: minor (`8.3.0` → `8.4.0`) - Tailwind CSS v4
`theme.css` export
- [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**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [ ] I've reviewed the [Release
Workflow](./.cursor/rules/release-workflow.md) cursor rule
- [ ] 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
georgewrmarshall added a commit that referenced this pull request May 8, 2026
## **Description**

Follow-up to #1104 (`feat: new Toast API design`).

This PR realigns the React Native Toast API with the shipped Figma
component, current extension naming, and the intended consumer-facing
runtime usage.

The main changes are:
- split responsibilities into `<Toaster />` for the mounted renderer,
`toast(...)` for showing a toast, and `toast.dismiss()` for dismissal
- keep `<Toast />` as the presentational surface for Storybook, Code
Connect, and direct rendering when needed
- center the API on `title`, `description`, `severity`, optional
`startAccessory`, and `actionButtonLabel` / `actionButtonOnPress`
- add `ToastSeverity.Default` as the no-icon default and align supported
severities to `Default`, `Success`, `Warning`, and `Danger`
- route built-in severity icons through `IconAlert`, while keeping
`startAccessory` as the override path
- always show the close button, default `hasNoTimeout` to `false`, and
rename `iconProps` to `iconAlertProps`
- update Figma, Code Connect, stories, README, migration guidance, and
tests to match the final API

Example runtime usage after this PR:

```tsx
import {
  Button,
  Toaster,
  toast,
  ToastSeverity,
} from '@metamask/design-system-react-native';

const Demo = () => (
  <>
    <Button
      onPress={() => {
        toast({
          title: 'File saved successfully',
          description: 'Your latest changes are now available.',
          severity: ToastSeverity.Success,
        });
      }}
    >
      Show Toast
    </Button>
    <Toaster />
  </>
);
```

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-695
Related:
- #1104

## **Manual testing steps**

1. Check out this branch.
2. Run `yarn build`.
3. Run `yarn test`.
4. Run `yarn lint`.
5. Open the React Native Toast stories and verify `Default`, `Title`,
`Description`, `Severity`, `StartAccessory`, and `ActionButtonOnPress`.

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/fd611d06-de7e-41ee-b655-5a68aa9ca90e

## **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
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Breaking API refactor for Toast/Toaster (new exports, renamed/removed
methods and option shapes) plus moved animation/state logic into
`Toaster`, which can impact all consumers and toast dismissal behavior.
> 
> **Overview**
> Refactors the React Native toast system to a split model: a
root-mounted `Toaster` owns rendering/animation and registers the
imperative `toast(...)` + `toast.dismiss()` API, while `Toast` becomes a
presentational surface component intended for direct rendering
(Storybook/docs).
> 
> Aligns the public options/types with the shipped design by replacing
variant-specific unions with flat content-first props (`title`,
`description`, `actionButtonLabel`/`actionButtonOnPress`,
`startAccessory`) and introducing `ToastSeverity`
(`Default|Success|Warning|Danger`) with `IconAlert`-backed severity
icons (and `startAccessory` as the override). Updates runtime semantics
including `hasNoTimeout` defaulting to `false`, renaming `iconProps` to
`iconAlertProps`, and adjusting close-button handling
(`closeButtonProps`/`onClose`).
> 
> Updates exports, Storybook stories, Figma Code Connect, tests (new
`Toaster` + `toast` coverage, simplified `Toast` tests), and
migration/docs to reflect the new API and removals (`Toast.show/hide`,
`ToastVariant`, `ToastView`, and legacy option wrappers).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
66f31c3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request react-native

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants