[3/N] feat: Modal migration (extension)#1136
Conversation
📖 Storybook Preview |
📖 Storybook Preview |
Modal migration (extension)Modal migration (extension)
Modal migration (extension)Modal migration (extension)
ddf5756 to
71ee7c4
Compare
📖 Storybook Preview |
Modal migration (extension)Modal migration (extension)
71ee7c4 to
ea0dbaa
Compare
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d237976. Configure here.
| autoFocus = true, | ||
| initialFocusRef, | ||
| finalFocusRef, | ||
| restoreFocus, |
There was a problem hiding this comment.
Missing restoreFocus default value unlike sibling props
Low Severity
restoreFocus is destructured without a default value, unlike its sibling boolean props (isClosedOnOutsideClick = true, isClosedOnEscapeKey = true, autoFocus = true). This means ctx.restoreFocus is undefined instead of false when unset, despite the JSDoc documenting @default false. Both the test and story work around this by wrapping in Boolean() (String(Boolean(ctx.restoreFocus))) while the other three props use plain String() — confirming the value is unexpectedly undefined. A consumer checking ctx.restoreFocus === false would get the wrong result.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit d237976. Configure here.
There was a problem hiding this comment.
Can we address these comments? I think it makes sense to add the default here
|
|
||
| import type { ModalProps } from './Modal.types'; | ||
|
|
||
| export type ModalContextType = Omit<ModalProps, 'children'>; |
There was a problem hiding this comment.
Context type leaks all HTML div attributes
Low Severity
ModalContextType is defined as Omit<ModalProps, 'children'>, but ModalProps extends ComponentProps<'div'>. This means the exported public context type includes every HTML div attribute (onClick, style, id, role, className, etc.), even though the context value only ever populates the eight modal-specific fields. Consumers typing against ModalContextType see ~150 properties that are always undefined. A narrower dedicated type listing only the behavior-config fields would accurately reflect what the context actually provides.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit d237976. Configure here.
There was a problem hiding this comment.
The root API and behavior look aligned with the extension version, and the current test coverage gives reasonable confidence in the portal/context contract. I have one follow-up note on Storybook/docs parity: the story set is still thinner than the extension source today, but that seems appropriate to expand once the rest of the modal subcomponents are available so the examples can demonstrate the intended composed usage more realistically.
Could we also address the Cursor comments #1136 (review)
| ); | ||
|
|
||
| const Backdrop = ({ onClick }: { onClick?: () => void }) => ( | ||
| <Box |
There was a problem hiding this comment.
non-blocking: The current story set is enough for the root primitive, but it is still much thinner than the extension source stories for major modal behaviors. Once ModalContent, ModalHeader, and the rest of the modal family are merged, can we expand this with richer stories for the main behavior props so Storybook/docs better reflect the intended composed usage?
📖 Storybook Preview |
## 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 -->


Description
Added
Modalcomponent to DSR.Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-305
Manual testing steps
ModalcomponentScreenshots/Recordings
Before
Screen.Recording.2026-05-04.at.19.16.08.mov
After
Screen.Recording.2026-05-04.at.19.17.21.mov
Important
The animation is added in
ModalContentand it's handled in #1139Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Introduces a new portal-based
Modalroot component and new public exports (Modal,useModalContext,ModalProps), which can affect consumers via bundle API surface and runtime portal/context behavior. Risk is mitigated by added unit tests and Storybook coverage, but modal/focus behavior regressions are still possible in consuming apps.Overview
Adds new
Modalroot component that conditionally portals its subtree intodocument.bodywhenisOpenand provides modal behavior configuration to descendants viaModalContext/useModalContext.Exports
Modal,useModalContext, and related types (ModalProps,ModalContextType) from the component barrel, and adds Storybook (README.mdx+ stories) plus unit tests covering portal mount/unmount, ref/attribute forwarding, context defaults, and the outside-provider error case.Updates
MIGRATION.mdwith a Modal migration section documenting import-path swaps, prop/context shape notes, and the updateduseModalContexterror message (plus removal of the legacymm-modalclass hook).Reviewed by Cursor Bugbot for commit 9b0f7a9. Bugbot is set up for automated code reviews on this repo. Configure here.