Skip to content

refactor: align Toast API with severity and accessory#1143

Merged
georgewrmarshall merged 31 commits into
mainfrom
feat/toast-new-api-alignments
May 8, 2026
Merged

refactor: align Toast API with severity and accessory#1143
georgewrmarshall merged 31 commits into
mainfrom
feat/toast-new-api-alignments

Conversation

@georgewrmarshall

@georgewrmarshall georgewrmarshall commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

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:

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:

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

after720.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
  • 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
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).

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

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Nested prop bag type exported from entrypoint
    • Removed ToastCloseButtonProps from Toast entrypoint and package barrel to avoid exporting nested prop bag types.

Create PR

Or push these changes by commenting:

@cursor push 5a49edaeab
Preview (5a49edaeab)
diff --git a/packages/design-system-react-native/src/components/Toast/index.ts b/packages/design-system-react-native/src/components/Toast/index.ts
--- a/packages/design-system-react-native/src/components/Toast/index.ts
+++ b/packages/design-system-react-native/src/components/Toast/index.ts
@@ -4,7 +4,6 @@
   ToastOptions,
   ToastProps,
   ToastRef,
-  ToastCloseButtonProps,
 } from './Toast.types';
 export {
   TOAST_VISIBILITY_DURATION,

diff --git a/packages/design-system-react-native/src/components/index.ts b/packages/design-system-react-native/src/components/index.ts
--- a/packages/design-system-react-native/src/components/index.ts
+++ b/packages/design-system-react-native/src/components/index.ts
@@ -218,7 +218,6 @@
   ToastOptions,
   ToastProps,
   ToastRef,
-  ToastCloseButtonProps,
 } from './Toast';
 
 export { ButtonHero, ButtonHeroSize } from './ButtonHero';

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

Comment thread packages/design-system-react-native/src/components/Toast/index.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: ToastOptions-only props leak to native View
    • Updated Toaster to destructure and omit hasNoTimeout and bottomOffset before spreading props into Toast, preventing these non-view props from propagating to native views.

Create PR

Or push these changes by commenting:

@cursor push dce7216943
Preview (dce7216943)
diff --git a/packages/design-system-react-native/src/components/Toast/Toaster.tsx b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
--- a/packages/design-system-react-native/src/components/Toast/Toaster.tsx
+++ b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
@@ -153,6 +153,13 @@
       return null;
     }
 
+    // Strip ToastOptions-only fields so they don't propagate to native views.
+    const {
+      hasNoTimeout: _omitHasNoTimeout,
+      bottomOffset: _omitBottomOffset,
+      ...toastRenderableProps
+    } = toastOptions;
+
     return (
       <Animated.View
         onLayout={onAnimatedViewLayout}
@@ -160,7 +167,7 @@
         {...props}
       >
         <Toast
-          {...toastOptions}
+          {...toastRenderableProps}
           onClose={() => {
             closeToast();
             toastOptions.onClose?.();

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

Comment thread packages/design-system-react-native/src/components/Toast/Toaster.tsx Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

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

There are 5 total unresolved issues (including 2 from previous reviews).

Autofix Details

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

  • ✅ Fixed: Toast leaks hasNoTimeout and bottomOffset to native View
    • Filtered out hasNoTimeout and bottomOffset in Toaster before forwarding props to Toast, preventing them from reaching native views.
  • ✅ Fixed: ToastSharedProps exported as unnecessary public API
    • Removed ToastSharedProps from the Toast entrypoint and the components barrel exports.
  • ✅ Fixed: Raw View with inline styles in stories
    • Replaced <View style={{ gap: 8 }}> with <Box gap={2}> in the Toast story to use design tokens.

Create PR

Or push these changes by commenting:

@cursor push 5bb99bb309
Preview (5bb99bb309)
diff --git a/packages/design-system-react-native/src/components/Toast/Toast.stories.tsx b/packages/design-system-react-native/src/components/Toast/Toast.stories.tsx
--- a/packages/design-system-react-native/src/components/Toast/Toast.stories.tsx
+++ b/packages/design-system-react-native/src/components/Toast/Toast.stories.tsx
@@ -1,6 +1,6 @@
 import type { Meta, StoryObj } from '@storybook/react-native';
 import React from 'react';
-import { View } from 'react-native';
+import { Box } from '../Box';
 
 // External dependencies.
 import { Icon, IconColor, IconName, IconSize } from '../Icon';
@@ -62,12 +62,12 @@
 
 export const Severity: Story = {
   render: (args) => (
-    <View style={{ gap: 8 }}>
+    <Box gap={2}>
       <Toast {...args} severity={ToastSeverity.Default} text="Default" />
       <Toast {...args} severity={ToastSeverity.Success} text="Success" />
       <Toast {...args} severity={ToastSeverity.Warning} text="Warning" />
       <Toast {...args} severity={ToastSeverity.Error} text="Error" />
-    </View>
+    </Box>
   ),
   args: {
     description: 'Severity controls the default start accessory icon.',

diff --git a/packages/design-system-react-native/src/components/Toast/Toaster.tsx b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
--- a/packages/design-system-react-native/src/components/Toast/Toaster.tsx
+++ b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
@@ -120,6 +120,13 @@
       return null;
     }
 
+    // Filter out internal-only options that should not reach native views.
+    const {
+      hasNoTimeout: _ignoredHasNoTimeout,
+      bottomOffset: _ignoredBottomOffset,
+      ...toastForwardProps
+    } = toastOptions;
+
     const onAnimatedViewLayout = (e: LayoutChangeEvent) => {
       const { height } = e.nativeEvent.layout;
       const translateYToValue = -(TOAST_BOTTOM_PADDING + bottomNotchSpacing);
@@ -155,7 +162,7 @@
         {...props}
       >
         <Toast
-          {...toastOptions}
+          {...toastForwardProps}
           onClose={() => {
             closeToast();
             toastOptions.onClose?.();

diff --git a/packages/design-system-react-native/src/components/Toast/index.ts b/packages/design-system-react-native/src/components/Toast/index.ts
--- a/packages/design-system-react-native/src/components/Toast/index.ts
+++ b/packages/design-system-react-native/src/components/Toast/index.ts
@@ -5,7 +5,6 @@
   ToastOptions,
   ToastProps,
   ToastCloseButtonProps,
-  ToastSharedProps,
   ToasterProps,
   ToasterRef,
 } from './Toast.types';

diff --git a/packages/design-system-react-native/src/components/index.ts b/packages/design-system-react-native/src/components/index.ts
--- a/packages/design-system-react-native/src/components/index.ts
+++ b/packages/design-system-react-native/src/components/index.ts
@@ -218,7 +218,6 @@
   ToastOptions,
   ToastProps,
   ToastCloseButtonProps,
-  ToastSharedProps,
   ToasterProps,
   ToasterRef,
 } from './Toast';

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

Comment thread packages/design-system-react-native/src/components/Toast/Toast.tsx
Comment thread packages/design-system-react-native/src/components/Toast/index.ts Outdated
Comment thread packages/design-system-react-native/src/components/Toast/Toast.stories.tsx Outdated
@georgewrmarshall georgewrmarshall force-pushed the feat/toast-new-api-alignments branch from 457e582 to 8901809 Compare May 6, 2026 18:44
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

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

There are 4 total unresolved issues (including 1 from previous review).

Autofix Details

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

  • ✅ Fixed: Toaster silently drops toast options' twClassName
    • Toaster now passes twClassName={toastProps.twClassName ?? twClassName} so per-toast classes are preserved.
  • ✅ Fixed: toast.dismiss() error message incorrectly says toast.hide()
    • Added 'dismiss' to the method union, updated error message construction, and toast.dismiss now reports toast.dismiss() correctly.
  • ✅ Fixed: ToastCloseButtonProps is exported but never used
    • Removed the unused ToastCloseButtonProps export from Toast.types.ts.

Create PR

Or push these changes by commenting:

@cursor push a1d31fff68
Preview (a1d31fff68)
diff --git a/packages/design-system-react-native/src/components/Toast/Toast.types.ts b/packages/design-system-react-native/src/components/Toast/Toast.types.ts
--- a/packages/design-system-react-native/src/components/Toast/Toast.types.ts
+++ b/packages/design-system-react-native/src/components/Toast/Toast.types.ts
@@ -23,13 +23,6 @@
 export type ToastIconProps = Omit<IconProps, 'name' | 'size' | 'color'>;
 
 /**
- * Optional props for the close `ButtonIcon`.
- */
-export type ToastCloseButtonProps = NonNullable<
-  BannerBaseProps['closeButtonProps']
->;
-
-/**
  * Shared toast props aligned with BannerBase, plus optional severity/icon props.
  */
 export type ToastSharedProps = BannerBaseProps & {

diff --git a/packages/design-system-react-native/src/components/Toast/Toaster.tsx b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
--- a/packages/design-system-react-native/src/components/Toast/Toaster.tsx
+++ b/packages/design-system-react-native/src/components/Toast/Toaster.tsx
@@ -39,12 +39,11 @@
 
 let registeredRef: RefObject<ToasterRef> | null = null;
 
-const assertRegisteredRef = (method: 'hide' | 'show' | 'toast'): ToasterRef => {
+const assertRegisteredRef = (
+  method: 'hide' | 'show' | 'toast' | 'dismiss',
+): ToasterRef => {
   if (!registeredRef?.current) {
-    const invocation =
-      method === 'toast'
-        ? 'toast()'
-        : `toast.${method === 'hide' ? 'hide' : 'show'}()`;
+    const invocation = method === 'toast' ? 'toast()' : `toast.${method}()`;
     throw new Error(
       `${invocation} called before <Toaster /> mounted. Render <Toaster /> once at the root of your app.`,
     );
@@ -175,7 +174,7 @@
             closeToast();
             toastOnClose?.();
           }}
-          twClassName={twClassName}
+          twClassName={toastProps.twClassName ?? twClassName}
         />
       </Animated.View>
     );
@@ -205,5 +204,5 @@
 };
 
 toast.dismiss = () => {
-  assertRegisteredRef('hide').closeToast();
+  assertRegisteredRef('dismiss').closeToast();
 };

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

Comment thread packages/design-system-react-native/src/components/Toast/Toaster.tsx Outdated
Comment thread packages/design-system-react-native/src/components/Toast/Toast.types.ts Outdated
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Rest props spread overrides Toast's hardcoded visual identity
    • Moved {...props} before explicit props so component-owned defaults and onClose nullification cannot be overridden.

Create PR

Or push these changes by commenting:

@cursor push eccfc114b1
Preview (eccfc114b1)
diff --git a/packages/design-system-react-native/src/components/Toast/Toast.tsx b/packages/design-system-react-native/src/components/Toast/Toast.tsx
--- a/packages/design-system-react-native/src/components/Toast/Toast.tsx
+++ b/packages/design-system-react-native/src/components/Toast/Toast.tsx
@@ -73,6 +73,7 @@
   return (
     <BannerBase
       {...actionProps}
+      {...props}
       backgroundColor={BoxBackgroundColor.BackgroundSection}
       borderColor={BoxBorderColor.BorderMuted}
       borderWidth={1}
@@ -97,7 +98,6 @@
       title={title}
       titleProps={titleProps}
       twClassName={twClassName ? `rounded-xl ${twClassName}` : 'rounded-xl'}
-      {...props}
     />
   );
 };

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

Comment thread packages/design-system-react-native/src/components/Toast/Toast.tsx
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@@ -3,129 +3,143 @@
Toast is a component that slides up from the bottom of the screen. It is typically used to show post-confirmation information such as account switches, network changes, or transaction confirmations.

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.

A bit hard to read from the changes, Toast has a slightly different readme template as it's not a typical jsx component. We need to communicate setup and the toast() api

docs720.mov

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

example: ({ severity, title, description, actionButton }) => {
const resolvedActionButtonLabel = actionButton?.label || undefined;

return (

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.

The mapped Figma node is still the visual Toast surface, but the example intentionally shows Toaster plus toast(...) because that is the consumer-facing runtime API we want Dev Mode readers to copy into app code.


useImperativeHandle(ref, () => innerRef.current as ToasterRef);

useLayoutEffect(() => {

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.

useLayoutEffect keeps the imperative API registered before sibling passive mount effects run, which avoids a mount-time race when an app calls toast() during initial render effects.


<!-- TODO: Replace 0.x.0 with the actual next released version when this Toast follow-up ships. -->

### From version 0.23.0 to 0.x.0

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.

This migration section is separate from the earlier Toast migration because 0.23.0 already shipped the first API shape to consumers. Reviewers should treat this as a second breaking follow-up, not just unreleased cleanup on top of #1104.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

But I don't think we started to use Toast component anywhere yet?..

Would it make sense to re-phrase current migration API? Because basic migration path + specific changes for 0.23..0.24 make more cognitive load. And since we released, but didn't start to use the new component I think it's fine just silently re-write the existing migration documentation 🤫

style={baseStyle}
{...props}
>
{actionButtonLabel && actionButtonOnPress ? (

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.

The explicit action-button branch here is mostly for type safety: BannerBase models action props as a union, so narrowing before render lets Toaster preserve label-only toast options without widening every Toast call site.

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment on lines -6 to -10
ToastRef,
ToastLabelOptions,
ToastDescriptionOptions,
ToastLinkButtonOptions,
ToastCloseButtonOptions,

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.

Removing imports of unused and unnecessary types

@@ -1,9 +1,18 @@
// External dependencies.
import { IconAlertSeverity } from '@metamask/design-system-shared';
import { AnimationDuration } from '@metamask/design-tokens';

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.

Importing IconAlertSeverity for IconAlert usage

export const TOAST_SEVERITY_ICON_MAP = {
[ToastSeverity.Success]: IconAlertSeverity.Success,
[ToastSeverity.Warning]: IconAlertSeverity.Warning,
[ToastSeverity.Danger]: IconAlertSeverity.Error,

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 we are mapping Danger to Error as we will be consolidating to Danger moving forward

Comment on lines +52 to +61
toast({
severity,
title,
description,
actionButtonLabel: resolvedActionButtonLabel,
actionButtonOnPress: resolvedActionButtonLabel
? () => undefined
: undefined,
});
}}

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.

Code connect file looks a little different from usual as we need to map it to the toast() function

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: closeButtonProps.onPress silently ignored due to BannerBase early-return
    • Updated React Native BannerBase handleClosePress to invoke both onClose and closeButtonProps.onPress so the consumer handler is no longer ignored.

Create PR

Or push these changes by commenting:

@cursor push 7866573597
Preview (7866573597)
diff --git a/packages/design-system-react-native/src/components/BannerBase/BannerBase.tsx b/packages/design-system-react-native/src/components/BannerBase/BannerBase.tsx
--- a/packages/design-system-react-native/src/components/BannerBase/BannerBase.tsx
+++ b/packages/design-system-react-native/src/components/BannerBase/BannerBase.tsx
@@ -55,10 +55,9 @@
   const handleClosePress =
     onClose || closeButtonPropsOnPress
       ? (event: GestureResponderEvent) => {
-          if (onClose) {
-            onClose();
-            return;
-          }
+          // Invoke both handlers when provided to allow parent onClose
+          // and consumer-provided closeButtonProps.onPress to run.
+          onClose?.();
           closeButtonPropsOnPress?.(event);
         }
       : undefined;

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

Reviewed by Cursor Bugbot for commit 5eb5853. Configure here.

Comment thread packages/design-system-react-native/src/components/Toast/Toast.tsx
@georgewrmarshall georgewrmarshall force-pushed the feat/toast-new-api-alignments branch from 5eb5853 to 66f31c3 Compare May 7, 2026 21:37
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@kirillzyusko kirillzyusko left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 🚀

@georgewrmarshall georgewrmarshall merged commit 560ccc0 into main May 8, 2026
44 checks passed
@georgewrmarshall georgewrmarshall deleted the feat/toast-new-api-alignments branch May 8, 2026 16:33
brianacnguyen added a commit that referenced this pull request May 8, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@brianacnguyen brianacnguyen mentioned this pull request May 8, 2026
20 tasks
georgewrmarshall pushed a commit that referenced this pull request May 8, 2026
## Release 39.0.0

This release adds Tailwind CSS v4 integration via
`@metamask/design-tokens/tailwind/theme.css`, ships extension migration
UI on React web (`Modal`, `ModalContent`, `Skeleton`, `HeaderBase`),
adds Tailwind preset animations (`animate-slide-up`,
`animate-skeleton-pulse`), and refreshes the shared icon set
(`ListArrow`, `Musd`, `MusdFilled`, `Group`, `PieChart`, `Predictions`,
refreshed `Candlestick`, `Musd` SVG fix) across
`@metamask/design-system-shared`, React, and React Native. **React
Native** also ships a **breaking** Toast follow-up
([#1143](#1143)):
root **`Toaster`**, imperative **`toast`** / **`toast.dismiss()`**, and
flat **`ToastSeverity`** options. The TWRNC preset widens its React peer
range for newer React Native / React stacks.

### 📦 Package Versions

- `@metamask/design-tokens`: **8.4.0**
- `@metamask/design-system-shared`: **0.17.0**
- `@metamask/design-system-react`: **0.22.0**
- `@metamask/design-system-react-native`: **0.24.0**
- `@metamask/design-system-tailwind-preset`: **0.8.0**
- `@metamask/design-system-twrnc-preset`: **0.4.2**

### 🎨 Design Tokens (8.4.0)

#### Added (#1117)

**What changed**

- Added `@metamask/design-tokens/tailwind/theme.css` for Tailwind CSS v4
so consumers can import MetaMask token variables, theme values,
typography, font, and shadow utilities in one place.

**Impact**

- Web apps on Tailwind v4 can adopt the token theme without hand-rolling
CSS variables; see [Tailwind CSS v3 to
v4](./packages/design-tokens/MIGRATION.md#tailwind-css-v3-to-v4).

### 🪶 `@metamask/design-system-tailwind-preset` (0.8.0)

#### Added

- **`animate-slide-up`** (and `slide-up` keyframes) for the same dialog
entrance motion as `ModalContent`
([#1139](#1139))
- **`animate-skeleton-pulse`** (and `skeleton-pulse` keyframes) for
loading placeholders used with `Skeleton`
([#1146](#1146))

### 📲 `@metamask/design-system-twrnc-preset` (0.4.2)

#### Changed (#844)

- Expanded the `react` peer dependency range to `>=18.2.0` so the preset
installs cleanly alongside React Native 0.76 and React 19 app stacks.

### 🔄 Shared Type Updates (0.17.0)

#### Shared icon set (#1157, #1161, #1162, #1163)

**What changed**

- Extended the shared icon set with `ListArrow`, `Musd`, `MusdFilled`,
`Group`, `PieChart`, and `Predictions`, refreshed the `Candlestick`
icon, and corrected the `Musd` asset to use a single SVG path.

**Impact**

- Keeps `IconName` and assets aligned for
`@metamask/design-system-react` and
`@metamask/design-system-react-native`.

### 🌐 React Web Updates (0.22.0)

#### Added

- Added `Modal` and `ModalContent` for dialogs, `Skeleton` for loading
placeholders, and `HeaderBase` for header layouts—supporting the
MetaMask extension migration into the design system
([#1136](#1136),
[#1139](#1139),
[#1146](#1146),
[#1142](#1142))
- Added icons `ListArrow`, `Musd`, `MusdFilled`, `Group`, `PieChart`,
and `Predictions`, and updated the `Candlestick` icon
([#1157](#1157),
[#1161](#1161),
[#1162](#1162))

#### Fixed

- Corrected the `Musd` icon asset so it renders from a single SVG path
([#1163](#1163))

### 📱 React Native Updates (0.24.0)

#### Added

- Added icons `ListArrow`, `Musd`, `MusdFilled`, `Group`, `PieChart`,
and `Predictions`, and updated the `Candlestick` icon
([#1157](#1157),
[#1161](#1161),
[#1162](#1162))

#### Changed

- **BREAKING:** Toast API follow-up
([#1143](#1143)):
mount **`<Toaster />`** once at the root; use **`toast(...)`** /
**`toast.dismiss()`** instead of **`Toast.show(...)`** /
**`Toast.hide()`**; content-first options with **`ToastSeverity`** and
**`iconAlertProps`** (renamed from **`iconProps`**). See [Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0230-to-0240).

#### Fixed

- Corrected the `Musd` icon asset so it renders from a single SVG path
([#1163](#1163))

### ⚠️ Breaking Changes

#### React Native — Toast (#1143)

**What changed**

- Imperative API moves from **`Toast.show`** / **`Toast.hide`** on
**0.23.x** to **`toast`** / **`toast.dismiss()`** with a root
**`<Toaster />`**.
- Options flatten to **`title`**, **`description`**, **`severity`**
(**`ToastSeverity`**), accessories, and **`iconAlertProps`**; map
**`ToastVariant`**-style payloads from **0.23.0** using the migration
guide.

**Migration**

- See [From version 0.23.0 to
0.24.0](./packages/design-system-react-native/MIGRATION.md#from-version-0230-to-0240)
(and [Toast
Component](./packages/design-system-react-native/MIGRATION.md#toast-component)
for component-library migration context).

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-tokens: minor (8.3.0 → 8.4.0) — Tailwind v4 `theme.css`
entry point
- [x] design-system-shared: minor (0.16.0 → 0.17.0) — shared icon set
additions and asset fixes
- [x] design-system-react: minor (0.21.0 → 0.22.0) — extension migration
components and icons
- [x] design-system-react-native: minor (0.23.0 → 0.24.0) — **breaking
Toast follow-up (#1143)**, icons, `Musd` fix
- [x] design-system-tailwind-preset: minor (0.7.0 → 0.8.0) —
`animate-slide-up` and `animate-skeleton-pulse` for ModalContent /
Skeleton
- [x] design-system-twrnc-preset: patch (0.4.1 → 0.4.2) — wider `react`
peer range
- [x] Breaking changes documented with migration guidance (React Native
Toast — see MIGRATION.md link above)
- [x] Migration guides updated with before/after examples (Toast **0.23
→ 0.24**; Tailwind v4 consumers — design-tokens migration link above)
- [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
(**React Native Toast** — [0.23.0 →
0.24.0](./packages/design-system-react-native/MIGRATION.md#from-version-0230-to-0240))
- [ ] All unreleased changes are accounted for in changelogs


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Primarily a release/version bump, but it changes published package
versions and updates peer dependency requirements, which can affect
downstream installs. React Native release notes include a breaking
`Toast` API change that consumers must account for when upgrading.
> 
> **Overview**
> Bumps the monorepo release to `39.0.0` and increments package versions
for `@metamask/design-system-react` (`0.22.0`),
`@metamask/design-system-react-native` (`0.24.0`),
`@metamask/design-system-shared` (`0.17.0`), and
`@metamask/design-system-tailwind-preset` (`0.8.0`), updating
corresponding changelogs and compare links.
> 
> Updates `@metamask/design-system-react` to require
`@metamask/design-system-tailwind-preset@^0.8.0` (and aligns
`yarn.lock`). Changelogs capture the release contents, including new
modal/skeleton/header additions on web, icon set updates across
packages, and a **breaking** React Native `Toast` API tightening for
`Toaster`/`toast(...)` usage.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4e3ea63. 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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants