Skip to content

[4/N] feat: ModalContent migration (extension)#1139

Merged
kirillzyusko merged 7 commits into
mainfrom
feat/modal-content-migration
May 7, 2026
Merged

[4/N] feat: ModalContent migration (extension)#1139
kirillzyusko merged 7 commits into
mainfrom
feat/modal-content-migration

Conversation

@kirillzyusko

@kirillzyusko kirillzyusko commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

Description

Added ModalContent component to DSR.

Related issues

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

Manual testing steps

  1. Open Storybook
  2. Check ModalContent example

Screenshots/Recordings

Before

Screen.Recording.2026-05-04.at.18.23.08.mov

After

Screen.Recording.2026-05-04.at.18.06.14.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
Adds new modal interaction logic (Escape/outside-click handling and focus behavior) and a new Tailwind animation, which could affect close behavior and portal-based popovers if the opt-out attribute is not applied consistently.

Overview
Adds a new ModalContent component to @metamask/design-system-react, including sizing tokens, focus integration, and document-level Escape/outside-click close handling that is configurable via Modal context.

Introduces a generic outside-click opt-out mechanism via MODAL_CONTENT_IGNORE_OUTSIDE_CLICK_ATTR (replacing the legacy hard-coded .mm-popover exception) and adds a new slide-up animation to the Tailwind preset used by the dialog.

Updates Storybook to use the new modal composition (ModalOverlay + ModalContent + ModalBody), adds dedicated ModalContent stories/tests/docs, and extends MIGRATION.md with a new ModalContent migration section and follow-up guidance for Popover-in-Modal behavior.

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

@kirillzyusko kirillzyusko self-assigned this Apr 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@kirillzyusko kirillzyusko changed the title [3/N] feat: ModalContent migration (extension) [5/N] feat: ModalContent migration (extension) Apr 30, 2026
@kirillzyusko kirillzyusko changed the title [5/N] feat: ModalContent migration (extension) [3/N] feat: ModalContent migration (extension) Apr 30, 2026
@kirillzyusko kirillzyusko force-pushed the feat/modal-content-migration branch from 6e92c37 to 15a62ce Compare May 4, 2026 14:10
@kirillzyusko kirillzyusko force-pushed the feat/modal-migration branch from ddf5756 to 71ee7c4 Compare May 4, 2026 14:15
@kirillzyusko kirillzyusko force-pushed the feat/modal-content-migration branch from 15a62ce to 3bd21d5 Compare May 4, 2026 14:23
@kirillzyusko kirillzyusko changed the title [3/N] feat: ModalContent migration (extension) [4/N] feat: ModalContent migration (extension) May 4, 2026
@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@kirillzyusko kirillzyusko force-pushed the feat/modal-migration branch from 71ee7c4 to ea0dbaa Compare May 4, 2026 16:35
kirillzyusko added a commit that referenced this pull request May 5, 2026
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Added `Modal` component to DSR.

## **Related issues**

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

## **Manual testing steps**

1. Open Storybook
2. Check `Modal` component

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**



https://github.com/user-attachments/assets/a42f3b88-ee65-4714-b34c-8e9190f5dc74



### **After**



https://github.com/user-attachments/assets/704d2f49-ed60-45a2-a306-660f041574dc


> [!IMPORTANT]
> The animation is added in `ModalContent` and it's handled in
#1139


## **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**
> Introduces a new portal-based `Modal` root 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 `Modal` root component** that conditionally portals its
subtree into `document.body` when `isOpen` and provides modal behavior
configuration to descendants via `ModalContext`/`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.md` with a **Modal migration section** documenting
import-path swaps, prop/context shape notes, and the updated
`useModalContext` error message (plus removal of the legacy `mm-modal`
class hook).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9b0f7a9. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: George Marshall <georgewrmarshall@gmail.com>
Base automatically changed from feat/modal-migration to main May 5, 2026 21:08
@kirillzyusko kirillzyusko force-pushed the feat/modal-content-migration branch from b7d63d9 to 4681654 Compare May 6, 2026 10:44
@kirillzyusko kirillzyusko marked this pull request as ready for review May 6, 2026 10:45
@kirillzyusko kirillzyusko requested a review from a team as a code owner May 6, 2026 10:45
@github-actions

github-actions Bot commented May 6, 2026

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.

ModalContent still has one blocking issue before I think this is ready: the unresolved modalDialogProps.asChild override can remove the dialog semantics when consumers pass asChild: false. I’m not duplicating the existing Bugbot inline thread for that, but I would keep this in request-changes until it’s fixed. I also left two non-blocking follow-ups for the Storybook wiring and migration guide duplication.

);
};

export const Default: Story = {

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.

suggestion: wire the Default story through args and pass them into ModalContent. Right now the size/className controls in argTypes are inert, so the primary Canvas is not exercising the API the docs expose.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed 👍

- `Modal` always renders a `<div>` and forwards arbitrary HTML attributes (`id`, `role`, `data-*`, `aria-*`, `ref`) to it. The `mm-modal` class hook is gone — use `className` to apply Tailwind utilities.
- `useModalContext` is now exported from the package barrel (`@metamask/design-system-react`). `ModalContextType` is also exported as a type for consumers building custom subtree integrations.

### Modal Component

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.

non-blocking: this file now has two identical ### Modal Component sections back-to-back. Dropping the duplicate keeps the migration guide navigable and avoids duplicate heading anchors.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thank you, fixed it!

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react/src/components/ModalContent/README.mdx
@kirillzyusko kirillzyusko force-pushed the feat/modal-content-migration branch from 8efebf2 to 8e13417 Compare May 7, 2026 18:44
@kirillzyusko kirillzyusko enabled auto-merge (squash) May 7, 2026 18:44
@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 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 8e13417. Configure here.

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@kirillzyusko kirillzyusko merged commit 663adc0 into main May 7, 2026
44 checks passed
@kirillzyusko kirillzyusko deleted the feat/modal-content-migration branch May 7, 2026 19:45
georgewrmarshall pushed a commit that referenced this pull request May 7, 2026
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Added `ModalContent` component to DSR.

## **Related issues**

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

## **Manual testing steps**

1. Open Storybook
2. Check `ModalContent` example

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**



https://github.com/user-attachments/assets/a38f1d99-b1bb-47b0-8591-0d8f02469cd1



### **After**


https://github.com/user-attachments/assets/106d987a-ec10-41f3-bc98-4e725454bda3

## **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**
> Introduces new modal interaction logic (document-level event
listeners, focus handling, and outside-click heuristics) that can affect
close behavior and accessibility across consumers.
> 
> **Overview**
> Adds a new `ModalContent` component to `@metamask/design-system-react`
and exports it (plus `ModalContentSize` and
`MODAL_CONTENT_IGNORE_OUTSIDE_CLICK_ATTR`) from the package barrel.
> 
> `ModalContent` owns the modal shell behavior (centered dialog sizing,
slide-up entrance animation, close-on-Escape and close-on-outside-click)
and introduces a **data-attribute opt-out**
(`data-mm-modal-ignore-outside-click`) for portal-rendered floating UI
siblings.
> 
> Updates Storybook to demonstrate the new modal composition
(`ModalOverlay` + `ModalContent` + `ModalBody`), adds dedicated
`ModalContent` stories/docs/tests, extends the Tailwind preset with a
`slide-up` keyframe/animation, and documents the migration guidance in
`MIGRATION.md`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8efebf2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@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 -->
@brianacnguyen brianacnguyen mentioned this pull request May 15, 2026
17 tasks
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