feat: migrate MainActionButton to design-system-react-native#952
Conversation
dd39cd1 to
d06237a
Compare
📖 Storybook Preview |
📖 Storybook Preview |
e91636c to
3ccca16
Compare
📖 Storybook Preview |
georgewrmarshall
left a comment
There was a problem hiding this comment.
Left some comments
| export const ActionButtonOnPress: Story = { | ||
| args: { | ||
| iconName: IconName.Add, | ||
| label: 'Tap me', | ||
| isDisabled: false, | ||
| }, | ||
| }; |
There was a problem hiding this comment.
Let's remove this story
| export const TWCLASS_MAINACTIONBUTTON_BASE = | ||
| 'items-center justify-center rounded-xl px-1 py-4 min-w-[68px]'; | ||
|
|
||
| export const TWCLASS_MAINACTIONBUTTON_CONTAINER = | ||
| 'items-center justify-center w-full'; | ||
|
|
||
| export const TWCLASS_MAINACTIONBUTTON_LABEL = | ||
| 'mt-0.5 w-full text-center shrink'; |
There was a problem hiding this comment.
These can all be applied directly in the component file
3ccca16 to
9844bbb
Compare
📖 Storybook Preview |
📖 Storybook Preview |
| onPress: { | ||
| action: 'pressed', | ||
| description: 'Callback fired when the action button is pressed.', | ||
| }, |
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
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:
labelPropstype allows props silently overridden at runtime- Added 'numberOfLines' and 'ellipsizeMode' to the labelProps Omit type to align types with hardcoded Text props.
Or push these changes by commenting:
@cursor push 7f0a0c1dfe
Preview (7f0a0c1dfe)
diff --git a/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.types.ts b/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.types.ts
--- a/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.types.ts
+++ b/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.types.ts
@@ -31,7 +31,13 @@
*/
labelProps?: Omit<
Partial<TextProps>,
- 'children' | 'variant' | 'fontWeight' | 'color' | 'twClassName'
+ | 'children'
+ | 'variant'
+ | 'fontWeight'
+ | 'color'
+ | 'twClassName'
+ | 'numberOfLines'
+ | 'ellipsizeMode'
>;
/**
* Disables the button interaction and applies disabled styling.| disabled={isDisabled} | ||
| accessible | ||
| onPress={!isDisabled ? onPress : undefined} | ||
| onPressIn={!isDisabled ? onPressIn : undefined} |
There was a problem hiding this comment.
Disabled state explicitly removes onPressIn and onPressOut alongside onPress so integrations do not run side effects while the button is non-interactive.
| ) as StyleProp<ViewStyle>; | ||
|
|
||
| const additionalStyle = | ||
| typeof style === 'function' ? style({ pressed }) : style; |
There was a problem hiding this comment.
The style callback runs for both pressed and idle states and merges after base tokens so consumers can layer interaction overrides without replacing layout defaults.
| * Optional props forwarded to the internal Text component. | ||
| * Useful for test IDs and accessibility metadata. | ||
| */ | ||
| labelProps?: Omit< |
There was a problem hiding this comment.
iconProps and labelProps intentionally omit controlled visual props so size, color, and typography stay consistent while still allowing test IDs and accessibility metadata.
| expect(onPress).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| it('does not call press handlers when disabled', () => { |
There was a problem hiding this comment.
This disabled interaction test exercises press, pressIn, and pressOut together because guarding all three handlers prevents downstream side effects in analytics and navigation hooks.
0e46f38 to
a19f71a
Compare
📖 Storybook Preview |
a19f71a to
bb0880b
Compare
📖 Storybook Preview |
| description="No results found" | ||
| actionButtonText="Try Again" | ||
| onAction={() => { | ||
| // eslint-disable-next-line no-console |
There was a problem hiding this comment.
Fixes eslint warning for unused eslint disablle comment
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Story export
IconNameshadows imported enumIconName- Renamed the story export from
IconNametoIconStoryand setname: 'IconName'so references in renders now resolve to the imported enum without changing the story's displayed name.
- Renamed the story export from
Or push these changes by commenting:
@cursor push a0de1bc250
Preview (a0de1bc250)
diff --git a/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.stories.tsx b/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.stories.tsx
--- a/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.stories.tsx
+++ b/packages/design-system-react-native/src/components/MainActionButton/MainActionButton.stories.tsx
@@ -89,7 +89,8 @@
},
};
-export const IconName: Story = {
+export const IconStory: Story = {
+ name: 'IconName',
parameters: {
actions: {
disable: true,
📖 Storybook Preview |
a3a299e to
e67d853
Compare
📖 Storybook Preview |
## Release 25.0.0 This release includes new components migrated from Extension and Mobile, breaking API improvements to ButtonIcon and Input components, and continued ADR-0003/0004 type migrations. ### 📦 Package Versions - `@metamask/design-system-shared`: **0.4.0** - `@metamask/design-system-react`: **0.11.0** - `@metamask/design-system-react-native`: **0.11.0** ### 🔄 Shared Type Updates (0.4.0) #### Component Type Additions (#964, #955) Added shared types for newly migrated components following ADR-0003 and ADR-0004 patterns: **What Changed:** - Added `ButtonFilter` shared types with `ButtonFilterVariant` const object and `ButtonFilterPropsShared` - Added `BannerBase` shared types with `BannerBaseSeverity` const object and `BannerBasePropsShared` **Impact:** - Enables consistent ButtonFilter and BannerBase implementations across React and React Native - Continues ADR-0003/0004 const-object + string-union pattern adoption ### 🌐 React Web Updates (0.11.0) #### Added - Added `ButtonFilter` component for filter button functionality (#964) - Added `BannerBase` component for creating custom banner notifications (#961) #### Changed - **BREAKING:** Updated `ButtonIcon` API to use `variant` prop instead of `isInverse` and `isFloating` boolean props (#948) - Updated `Ai` icon to filled version for visual consistency (#970) ### 📱 React Native Updates (0.11.0) #### Added - Added `ButtonFilter` component (#964) - Added `BottomSheet` component for modal interactions (#963) - Added `MainActionButton` component for primary CTAs (#952) - Added `BannerBase` component for custom banners (#955) - Added `ListItem` component for standardized list rows (#958) - Added `TabEmptyState` component for empty states (#949) - Added `BottomSheetDialog` component for dialogs (#905) #### Changed - **BREAKING:** Updated `ButtonIcon` API to use `variant` prop instead of `isInverse` and `isFloating` boolean props (#948) - **BREAKING:** `Input` component now requires `value` prop and is controlled-only (#960) - Updated `Ai` icon to filled version (#970) #### Fixed - Fixed iOS placeholder alignment issue in `Input` component (#960) - Fixed missing component exports (#967) ###⚠️ Breaking Changes #### ButtonIcon Variant Prop (Both Platforms) **What Changed:** - Removed `isInverse` and `isFloating` boolean props - Added `variant` prop with three options: - `ButtonIconVariant.Default` (transparent background - default) - `ButtonIconVariant.Filled` (muted background with rounded corners - new) - `ButtonIconVariant.Floating` (colored background with inverse icon - replaces `isFloating`) **Migration:** ```tsx // Before <ButtonIcon name={IconName.Add} isFloating /> // After <ButtonIcon name={IconName.Add} variant={ButtonIconVariant.Floating} /> ``` See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0100-to-0110) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0100-to-0110) #### Input Controlled-Only (React Native Only) **What Changed:** - Removed `defaultValue` prop - `value` prop is now required - All Input instances must be controlled with state management **Migration:** ```tsx // Before <Input placeholder="Enter text" defaultValue="Initial" onChange={handleChange} /> // After const [text, setText] = useState('Initial'); <Input placeholder="Enter text" value={text} onChange={setText} /> ``` **Impact:** - Affects `Input` and `TextField` components - Provides consistent behavior and fixes iOS placeholder alignment See [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0100-to-0110) for complete instructions. ### ✅ Checklist - [x] Changelogs updated with human-readable descriptions - [x] Changelog validation passed (`yarn changelog:validate`) - [x] Version bumps follow semantic versioning - design-system-shared: minor (0.3.0 → 0.4.0) - new shared types - design-system-react: minor (0.10.0 → 0.11.0) - new components + breaking ButtonIcon change - design-system-react-native: minor (0.10.0 → 0.11.0) - new components + breaking ButtonIcon and Input changes - [x] Breaking changes documented with migration guidance - [x] Migration guides updated with before/after examples - [x] PR references included in changelog entries <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Although this PR is mostly versioning/docs, it formalizes breaking public API changes (`ButtonIcon` and RN `Input`) that will require downstream updates and could cause consumer build failures if missed. > > **Overview** > Bumps the monorepo release to `25.0.0` and publishes new package versions (`@metamask/design-system-react@0.11.0`, `@metamask/design-system-react-native@0.11.0`, `@metamask/design-system-shared@0.4.0`) with updated changelogs. > > Documents newly added components/types (`ButtonFilter`, `BannerBase`, plus several React Native-only additions like `BottomSheet`, `ListItem`, etc.) and **breaking API changes**: `ButtonIcon` replaces `isInverse`/`isFloating` with a `variant` prop (React + RN), and React Native `Input` becomes controlled-only (requires `value`, removes `defaultValue`). Migration guides are updated with before/after examples and new compare links. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0148a27. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->


Description
Related issue
Screenshots
Mobile
mobile.main.action.button.mov
MMDS
mainactionbutton.mov
Notes
Note
Low Risk
Low risk: primarily adds a new UI component with isolated exports plus Storybook wiring and tests; minimal impact on existing runtime behavior aside from the new barrel export.
Overview
Adds a new
MainActionButtoncomponent todesign-system-react-native, including its implementation, typed props, README docs, Storybook stories, and a test suite covering disabled/press handling, prop forwarding, and style merging.Wires the component into the library and RN Storybook by exporting it from the components barrel and registering the new story; also makes a small cleanup to
TabEmptyStatestory’sonActionhandler comment.Written by Cursor Bugbot for commit e67d853. This will update automatically on new commits. Configure here.