Skip to content

refactor: simplify BannerBase close handling#1166

Merged
georgewrmarshall merged 5 commits into
mainfrom
refactor/bannerbase-close-api
May 8, 2026
Merged

refactor: simplify BannerBase close handling#1166
georgewrmarshall merged 5 commits into
mainfrom
refactor/bannerbase-close-api

Conversation

@georgewrmarshall

@georgewrmarshall georgewrmarshall commented May 7, 2026

Copy link
Copy Markdown
Contributor

Description

This PR simplifies BannerBase close handling in @metamask/design-system-react-native so onClose is the only behavioral close API. closeButtonProps is now customization-only, and the close button only renders when onClose is provided.

It also updates the related migration and usage docs so reviewers and downstream consumers have the current contract documented in one place.

Related issues

Fixes:

Manual testing steps

  1. Run yarn build
  2. Run yarn test
  3. Run yarn lint
  4. In the BannerBase stories/docs, confirm closeButtonProps is described as non-behavioral and that onClose is required to render the close button.

Screenshots/Recordings

Not applicable. This PR changes component API behavior and documentation only.

Before

Not applicable.

After

Not applicable.

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
Introduces a breaking behavior/type change in BannerBase (web + RN): close buttons no longer render or handle events via closeButtonProps, which can break downstream consumers and tests until updated.

Overview
BannerBase close handling is simplified across React and React Native. The close button now renders only when onClose is provided, and closeButtonProps is reduced to customization-only (removing closeButtonProps.onClick / closeButtonProps.onPress from the public types and wiring).

Tests, Storybook arg descriptions, and component READMEs are updated to reflect the new contract, and both packages’ MIGRATION.md add explicit breaking-change guidance. Release/migration process docs are also updated to clarify that package CHANGELOG.md edits should happen only on release branches, with breaking changes documented in MIGRATION.md during feature/migration PRs.

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

@georgewrmarshall georgewrmarshall requested a review from a team as a code owner May 7, 2026 21:57
brianacnguyen
brianacnguyen previously approved these changes May 7, 2026
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall marked this pull request as draft May 7, 2026 22:01

@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: Spread can override onClose via leaked onPress
    • Moved the close button props spread before the explicit onPress so any leaked onPress cannot override onClose at runtime.

Create PR

Or push these changes by commenting:

@cursor push 44a97483be
Preview (44a97483be)
diff --git a/packages/design-system-react-native/CHANGELOG.md b/packages/design-system-react-native/CHANGELOG.md
--- a/packages/design-system-react-native/CHANGELOG.md
+++ b/packages/design-system-react-native/CHANGELOG.md
@@ -7,6 +7,10 @@
 
 ## [Unreleased]
 
+### Changed
+
+- **BREAKING:** Simplified `BannerBase` close-button handling so `onClose` is the only behavioral close API; `closeButtonProps` now customizes the close `ButtonIcon` only and no longer accepts `onPress`. The close button is rendered only when `onClose` is provided. See [Migration Guide](./MIGRATION.md#from-version-0230-to-0x0).
+
 ## [0.23.0]
 
 ### Added

diff --git a/packages/design-system-react-native/MIGRATION.md b/packages/design-system-react-native/MIGRATION.md
--- a/packages/design-system-react-native/MIGRATION.md
+++ b/packages/design-system-react-native/MIGRATION.md
@@ -27,6 +27,7 @@
   - [TabEmptyState Component](#tabemptystate-component)
   - [Toast Component](#toast-component)
 - [Version Updates](#version-updates)
+  - [From version 0.23.0 to 0.x.0](#from-version-0230-to-0x0)
   - [From version 0.22.0 to 0.23.0](#from-version-0220-to-0230)
   - [From version 0.21.0 to 0.22.0](#from-version-0210-to-0220)
   - [From version 0.19.0 to 0.20.0](#from-version-0190-to-0200)
@@ -41,6 +42,28 @@
 
 ## Version Updates
 
+<!-- TODO: Replace 0.x.0 with the actual next released version when this BannerBase follow-up ships. -->
+
+### From version 0.23.0 to 0.x.0
+
+#### BannerBase: `onClose` is now the only close-button behavior API
+
+**What changed:**
+
+- **`closeButtonProps.onPress`** is removed from the public **`BannerBase`** API.
+- The close button now renders **only** when **`onClose`** is provided.
+- **`closeButtonProps`** is now customization-only for the rendered close **`ButtonIcon`**.
+
+**Migration:**
+
+- Move any close-button behavior from **`closeButtonProps.onPress`** to **`onClose`**.
+- Keep **`closeButtonProps`** only for non-behavioral customization such as **`testID`**, accessibility props, and styling hooks.
+- If you previously passed only **`closeButtonProps`** to force-render a close button, also provide **`onClose`** now.
+
+**Impact:**
+
+- Existing **`@metamask/design-system-react-native`** consumers that relied on **`closeButtonProps.onPress`** or on rendering a close button without **`onClose`** must update those call sites.
+
 ### From version 0.22.0 to 0.23.0
 
 #### Toast: static API replaces context-based usage
@@ -2099,21 +2122,21 @@
 
 ##### Renamed Props
 
-| Legacy Mobile API                            | MMDS API                                     |
-| -------------------------------------------- | -------------------------------------------- |
-| `actionButtonProps.onPress`                  | `actionButtonOnPress`                        |
-| `actionButtonProps.label`                    | `actionButtonLabel`                          |
-| `closeButtonProps.onPress` (still supported) | `closeButtonProps.onPress` (still supported) |
+| Legacy Mobile API           | MMDS API              |
+| --------------------------- | --------------------- |
+| `actionButtonProps.onPress` | `actionButtonOnPress` |
+| `actionButtonProps.label`   | `actionButtonLabel`   |
+| `closeButtonProps.onPress`  | **`onClose`**         |
 
 ##### Type and Callback Signature Changes
 
-| Legacy Mobile API                                       | MMDS API                                                                                                                            | Notes                                                                        |
-| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
-| `actionButtonProps?: ButtonProps`                       | `actionButtonProps?: Omit<Partial<ButtonProps>, 'children' \| 'onPress' \| 'variant'>`                                              | MMDS prevents setting action handler and variant through `actionButtonProps` |
-| `actionButtonProps` controls rendering of action button | `actionButtonOnPress` controls rendering of action button                                                                           | Action button is shown only when `actionButtonOnPress` is provided           |
-| `title?: string \| React.ReactNode`                     | `title?: ReactNode`                                                                                                                 | Equivalent content support                                                   |
-| `description?: string \| React.ReactNode`               | `description?: ReactNode`                                                                                                           | Equivalent content support                                                   |
-| `closeButtonProps?: ButtonIconProps`                    | `closeButtonProps?: Omit<Partial<ButtonIconProps>, 'iconName' \| 'onPress'> & { onPress?: (event: GestureResponderEvent) => void }` | `iconName` remains fixed to close icon                                       |
+| Legacy Mobile API                                       | MMDS API                                                                               | Notes                                                                        |
+| ------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
+| `actionButtonProps?: ButtonProps`                       | `actionButtonProps?: Omit<Partial<ButtonProps>, 'children' \| 'onPress' \| 'variant'>` | MMDS prevents setting action handler and variant through `actionButtonProps` |
+| `actionButtonProps` controls rendering of action button | `actionButtonOnPress` controls rendering of action button                              | Action button is shown only when `actionButtonOnPress` is provided           |
+| `title?: string \| React.ReactNode`                     | `title?: ReactNode`                                                                    | Equivalent content support                                                   |
+| `description?: string \| React.ReactNode`               | `description?: ReactNode`                                                              | Equivalent content support                                                   |
+| `closeButtonProps?: ButtonIconProps`                    | `closeButtonProps?: Omit<Partial<ButtonIconProps>, 'iconName' \| 'onPress'>`           | `iconName` remains fixed to close icon; use `onClose` for behavior           |
 
 ##### Default and Behavior Changes
 
@@ -2121,7 +2144,7 @@
 | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
 | Action button shown when `actionButtonProps` exists                      | Action button shown when `actionButtonOnPress` exists                                                              |
 | Action button defaults to `size={ButtonSize.Auto}`                       | Action button defaults to `size={ButtonSize.Md}`                                                                   |
-| Close button press fallback uses `noop` when callbacks are missing       | Close button callback is omitted when callbacks are missing                                                        |
+| Close button press fallback uses `noop` when callbacks are missing       | Close button is rendered only when `onClose` is provided                                                           |
 | Close button icon default color is `IconColor.Default`                   | MMDS `BannerBase` delegates icon color to `ButtonIcon` defaults unless explicitly overridden in `closeButtonProps` |
 | Close button accessibility label had no explicit default in `BannerBase` | Default close label is `'Close banner'` (override with `closeButtonProps.accessibilityLabel`)                      |
 

diff --git a/packages/design-system-react-native/src/components/BannerBase/BannerBase.stories.tsx b/packages/design-system-react-native/src/components/BannerBase/BannerBase.stories.tsx
--- a/packages/design-system-react-native/src/components/BannerBase/BannerBase.stories.tsx
+++ b/packages/design-system-react-native/src/components/BannerBase/BannerBase.stories.tsx
@@ -41,7 +41,8 @@
     },
     closeButtonProps: {
       control: 'object',
-      description: 'Optional props for the close button',
+      description:
+        'Optional non-behavioral props for the close button when onClose is provided',
     },
     startAccessory: {
       control: false,

diff --git a/packages/design-system-react-native/src/components/BannerBase/BannerBase.test.tsx b/packages/design-system-react-native/src/components/BannerBase/BannerBase.test.tsx
--- a/packages/design-system-react-native/src/components/BannerBase/BannerBase.test.tsx
+++ b/packages/design-system-react-native/src/components/BannerBase/BannerBase.test.tsx
@@ -97,12 +97,10 @@
     );
   });
 
-  it('renders close button and triggers closeButtonProps.onPress when onClose is not provided', () => {
-    const onCloseButtonPress = jest.fn();
-    const { getByTestId } = render(
+  it('does not render close button when only closeButtonProps are provided', () => {
+    const { queryByTestId } = render(
       <BannerBase
         closeButtonProps={{
-          onPress: onCloseButtonPress,
           accessibilityLabel: 'Dismiss banner',
           testID: closeButtonTestId,
           twClassName: 'p-2',
@@ -110,10 +108,6 @@
       />,
     );
 
-    expect(getByTestId(closeButtonTestId).props.accessibilityLabel).toBe(
-      'Dismiss banner',
-    );
-    fireEvent.press(getByTestId(closeButtonTestId));
-    expect(onCloseButtonPress).toHaveBeenCalledTimes(1);
+    expect(queryByTestId(closeButtonTestId)).toBeNull();
   });
 });

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
@@ -9,7 +9,6 @@
   TextVariant,
 } from '@metamask/design-system-shared';
 import React from 'react';
-import { GestureResponderEvent } from 'react-native';
 
 import { Box } from '../Box';
 import { Button } from '../Button';
@@ -44,25 +43,13 @@
 
   const {
     accessibilityLabel: closeButtonAccessibilityLabel = 'Close banner',
-    onPress: closeButtonPropsOnPress,
     twClassName: closeButtonTwClassName,
     ...resolvedCloseButtonProps
   } = closeButtonProps ?? {};
 
-  const shouldShowCloseButton = Boolean(onClose || closeButtonProps);
+  const shouldShowCloseButton = Boolean(onClose);
   const shouldShowActionButton = Boolean(actionButtonOnPress);
 
-  const handleClosePress =
-    onClose || closeButtonPropsOnPress
-      ? (event: GestureResponderEvent) => {
-          if (onClose) {
-            onClose();
-            return;
-          }
-          closeButtonPropsOnPress?.(event);
-        }
-      : undefined;
-
   const mergedCloseButtonTwClassName = closeButtonTwClassName
     ? `ml-3 ${closeButtonTwClassName}`
     : 'ml-3';
@@ -133,8 +120,8 @@
           iconName={IconName.Close}
           size={ButtonIconSize.Sm}
           accessibilityLabel={closeButtonAccessibilityLabel}
-          onPress={handleClosePress}
           {...resolvedCloseButtonProps}
+          onPress={onClose}
         />
       )}
     </Box>

diff --git a/packages/design-system-react-native/src/components/BannerBase/BannerBase.types.ts b/packages/design-system-react-native/src/components/BannerBase/BannerBase.types.ts
--- a/packages/design-system-react-native/src/components/BannerBase/BannerBase.types.ts
+++ b/packages/design-system-react-native/src/components/BannerBase/BannerBase.types.ts
@@ -14,12 +14,7 @@
 type BannerBaseCloseButtonProps = Omit<
   Partial<ButtonIconProps>,
   'iconName' | 'onPress'
-> & {
-  /**
-   * Optional press handler for the close button.
-   */
-  onPress?: (event: GestureResponderEvent) => void;
-};
+>;
 
 type BannerBasePropsBase = BannerBasePropsShared &
   Omit<BoxProps, 'children'> & {
@@ -42,7 +37,7 @@
     onClose?: () => void;
     /**
      * Optional props for the close `ButtonIcon`.
-     * Providing this also shows a close button.
+     * Only used when `onClose` is provided.
      */
     closeButtonProps?: BannerBaseCloseButtonProps;
   };

diff --git a/packages/design-system-react-native/src/components/BannerBase/README.md b/packages/design-system-react-native/src/components/BannerBase/README.md
--- a/packages/design-system-react-native/src/components/BannerBase/README.md
+++ b/packages/design-system-react-native/src/components/BannerBase/README.md
@@ -95,12 +95,12 @@
 
 ### `onClose`
 
-Optional close callback. If passed, a close button is shown. Use `closeButtonProps` to pass additional props to the close `ButtonIcon`, including `testID` when needed for testing.
+Optional close callback. If passed, a close button is shown. Use `closeButtonProps` to pass additional non-behavioral props to the close `ButtonIcon`, including `testID`, accessibility props, and styling hooks when needed for testing.
 
-| PROP               | TYPE                                                                                                             | REQUIRED | DEFAULT     |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------- | -------- | ----------- |
-| `onClose`          | `() => void`                                                                                                     | No       | `undefined` |
-| `closeButtonProps` | `Omit<Partial<ButtonIconProps>, 'iconName' \| 'onPress'> & { onPress?: (event: GestureResponderEvent) => void }` | No       | `undefined` |
+| PROP               | TYPE                                                      | REQUIRED | DEFAULT     |
+| ------------------ | --------------------------------------------------------- | -------- | ----------- |
+| `onClose`          | `() => void`                                              | No       | `undefined` |
+| `closeButtonProps` | `Omit<Partial<ButtonIconProps>, 'iconName' \| 'onPress'>` | No       | `undefined` |
 
 ```tsx
 <BannerBase

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

Reviewed by Cursor Bugbot for commit cf20ce4. Configure here.

@georgewrmarshall georgewrmarshall force-pushed the refactor/bannerbase-close-api branch 2 times, most recently from 6cb3450 to 1831e2b Compare May 7, 2026 22:05
@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 on lines +18 to +21
- ✅ **Edit package `CHANGELOG.md` files only on release branches** created by `yarn create-release-branch`
- ✅ **Run `yarn constraints --fix && yarn && yarn dedupe`** after release spec
- ❌ **NO manual peer dependency updates** - handled automatically by yarn workspaces (causes errors)
- ❌ **NO package `CHANGELOG.md` edits in normal feature/fix PRs** - document breaking changes in `MIGRATION.md` instead and let the release branch collect changelog entries

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.

Noticed that CHANGELOG.md is being updated a lot, so specifically instructing to only update changelog files during release process

Comment on lines +180 to +183
- In normal migration or feature PRs, document consumer-facing breaking changes in the relevant package `MIGRATION.md`.
- Do not manually update package `CHANGELOG.md` files in these PRs.
- Package changelog entries should only be added on release branches created by `yarn create-release-branch`.
- [Example PR](https://github.com/MetaMask/core/pull/2003/files): release-facing changelog work can happen as part of the release flow or in a separate follow-up release PR.

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.

Same changelog instructions here


- Move any close-button behavior from **`closeButtonProps.onPress`** to **`onClose`**.
- Keep **`closeButtonProps`** only for non-behavioral customization such as **`testID`**, accessibility props, and styling hooks.
- If you previously passed only **`closeButtonProps`** to force-render a close button, also provide **`onClose`** now.

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 note calls out the broader behavioral break as well: call sites that previously passed only closeButtonProps were relying on that object to force-render the close affordance, and now need to provide onClose explicitly.

@@ -14,12 +14,7 @@ type BannerBaseActionButtonProps = Omit<
type BannerBaseCloseButtonProps = Omit<

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 type change is the public API break: closeButtonProps stays available for visual and accessibility customization, but behavioral close handling now has a single entry point through onClose.

closeButtonProps: {
control: 'object',
description: 'Optional props for the close button',
description:

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 Storybook controls mirror the API cleanup so examples do not imply that closeButtonProps alone is enough to render a close affordance. That keeps interactive docs aligned with the new runtime behavior.

### `onClose`

Optional close callback. If passed, a close button is shown. Use `closeButtonProps` to pass additional props to the close `ButtonIcon`, including `testID` when needed for testing.
Optional close callback. If passed, a close button is shown. Use `closeButtonProps` to pass additional non-behavioral props to the close `ButtonIcon`, including `testID`, accessibility props, and styling hooks when needed for testing.

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 README now matches the runtime contract closely enough for downstream consumers: onClose is what makes the control exist, and closeButtonProps are only for tailoring the rendered ButtonIcon once that control exists.

- e.g. https://github.com/MetaMask/core/issues/1823

### 5. Record changes made to any metamask design system package in its CHANGELOG, under the `## [Unreleased]` heading
### 5. Document breaking changes in `MIGRATION.md`; reserve `CHANGELOG.md` for release branches

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 process update is here to stop a repeated source of drift: implementation PRs need migration guidance immediately, but package changelog entries are only authoritative once the release branch has collected the actual shipped version changes.

@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

@georgewrmarshall georgewrmarshall force-pushed the refactor/bannerbase-close-api branch from 2ec93f8 to 73a6915 Compare May 8, 2026 17:17
@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall marked this pull request as ready for review May 8, 2026 17:59
@georgewrmarshall georgewrmarshall force-pushed the refactor/bannerbase-close-api branch from 73a6915 to d6f48d2 Compare May 8, 2026 18:57
@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall merged commit 9f9c4d9 into main May 8, 2026
44 checks passed
@georgewrmarshall georgewrmarshall deleted the refactor/bannerbase-close-api branch May 8, 2026 19:08
@brianacnguyen brianacnguyen mentioned this pull request May 15, 2026
17 tasks
brianacnguyen added a commit that referenced this pull request May 15, 2026
## Release 40.0.0

This release updates the shared layer and both UI packages: new
extension-aligned primitives and form helpers on web, new selection and
multi-line input components on React Native, shared types and context
for those APIs, coordinated **`BannerBase`** close behavior, and
**`ButtonBase`** defaults driven by **`size`** (with migration guidance
for wrappers that overrode label, icon, or spacing).

### Package versions

- `@metamask/design-system-shared`: **0.18.0**
- `@metamask/design-system-react`: **0.23.0**
- `@metamask/design-system-react-native`: **0.25.0**

### Shared type updates (0.18.0)

#### Component type additions
([#1172](#1172),
[#1164](#1164),
[#1169](#1169),
[#1141](#1141))

**What changed**

- **`SelectButton`** shared props and variants
(`SelectButtonPropsShared`, `SelectButtonVariant`,
`SelectButtonEndArrow`).
- **`SegmentGroup`** shared props and **`SegmentGroupContext`**
(`SegmentGroupPropsShared`, `SegmentGroupContext`,
`SegmentGroupContextValue`).
- **`SensitiveText`** shared types (`SensitiveTextLength`,
`SensitiveTextPropsShared`, and related exports).
- **`HelpText`** shared types (`HelpTextSeverity`,
`HelpTextPropsShared`, and related exports).
- **`TextAreaPropsShared`** for multi-line input wrappers.

**Impact**

- React and React Native stay aligned on the same ADR-0003/0004-style
contracts for the new and updated surfaces above.

### React web updates (0.23.0)

#### Added

- **`PopoverHeader`** — popover title rows and trailing actions,
extension migration patterns
([#1158](#1158)).
- **`ModalHeader`** — modal title rows and accessory slots
([#1144](#1144)).
- **`Label`** — captions paired with form controls
([#1152](#1152)).
- **`SensitiveText`** — mask/reveal for sensitive strings with
configurable visible length
([#1164](#1164)).
- **`HelpText`** — helper, success, warning, and error copy under inputs
and controls
([#1169](#1169)).

#### Changed

- **`ButtonBase`** — label **`Text`** variant, start/end icon sizes, and
internal spacing are derived from **`size`** for each
**`ButtonBaseSize`**
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onClick`** is not the dismiss API;
**`closeButtonProps`** is for customization
([#1166](#1166)).

### React Native updates (0.25.0)

#### Added

- **`SelectButton`**, **`SegmentButton`**, **`SegmentGroup`**
([#1172](#1172)).
- **`SensitiveText`**, aligned with the shared contract
([#1164](#1164)).
- **`HeaderStandardAnimated`** and **`useHeaderStandardAnimated`**
([#1151](#1151)).
- **`TextArea`**
([#1141](#1141)).

#### Changed

- **`ButtonBase`** — same size-driven defaults as web
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onPress`** is not the dismiss API
([#1166](#1166)).

### Breaking changes

#### `BannerBase` close API (both platforms)

**What changed**

- **React:** Use **`onClose`** for dismiss behavior.
**`closeButtonProps.onClick`** is removed from that role. The close
control is tied to **`onClose`**. **`closeButtonProps`** remains for
non-behavioral customization (e.g. **`data-testid`**, accessibility,
styling hooks).
- **React Native:** Same pattern: **`onClose`** instead of
**`closeButtonProps.onPress`** for dismiss behavior.

**Migration**

- Move any close action from **`closeButtonProps.onClick`** /
**`closeButtonProps.onPress`** to **`onClose`**.
- If you previously forced a close button with only
**`closeButtonProps`**, also provide **`onClose`**.

**Impact**

- Call sites that dismissed via **`closeButtonProps`** or showed a close
button without **`onClose`** must be updated.

See:

- [React — From version 0.22.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#from-version-0220-to-0x0)
- [React Native — From version 0.24.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#from-version-0240-to-0x0)

**`ButtonBase`:** not called out here as a semver-breaking API change;
consumers who overrode typography, icon size, or spacing on
**`ButtonBase`** wrappers should follow the ButtonBase migration
sections linked above.

### Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] `yarn changelog:validate` passes
- [x] Version bumps follow semantic versioning
- [x] `@metamask/design-system-shared`: **minor** (0.17.x → 0.18.0) —
new shared exports for select/segment, sensitive text, help text, text
area
- [x] `@metamask/design-system-react`: **minor** (0.22.x → 0.23.0) — new
components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] `@metamask/design-system-react-native`: **minor** (0.24.x →
0.25.0) — new components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] Breaking changes documented (**`BannerBase`**) in MIGRATION with
before/after examples
- [x] PR references present in changelog entries

## Pre-merge author checklist

- [ ] [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [ ] [Release
Workflow](https://github.com/MetaMask/metamask-design-system/blob/main/.cursor/rules/release-workflow.md)
- [ ] `yarn build && yarn test && yarn lint`
- [ ] `yarn changelog:validate`

## Pre-merge reviewer checklist

- [ ] [Reviewing Release
PRs](https://github.com/MetaMask/metamask-design-system/blob/main/docs/reviewing-release-prs.md)
- [ ] Package versions and semver match what this PR actually publishes
- [ ] Changelogs are consumer-facing
- [ ] Breaking changes covered in MIGRATION.md
- [ ] No unpublished package is missing from the changelogs / version
list for **this** PR
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