Skip to content

chore: upgrade React Native v76.9 and Storybook v10 and align deps with MetaMask Mobile#844

Open
georgewrmarshall wants to merge 10 commits intomainfrom
upgrade-react-native
Open

chore: upgrade React Native v76.9 and Storybook v10 and align deps with MetaMask Mobile#844
georgewrmarshall wants to merge 10 commits intomainfrom
upgrade-react-native

Conversation

@georgewrmarshall
Copy link
Copy Markdown
Contributor

@georgewrmarshall georgewrmarshall commented Oct 21, 2025

Description

Upgrades the React Native Storybook app from Storybook 6.5 → v10 and aligns native dependencies with MetaMask Mobile (RN 0.76.9, React 18.3.1). This is a major infrastructure upgrade that modernizes the mobile component development environment.

Key changes

Storybook v10 Migration:

  • Migrated from .storybook/ to .rnstorybook/ (SB10 default config path)
  • New SB10 entry point using view.getStorybookUI() with AsyncStorage persistence
  • Added on-device addons: notes, controls, backgrounds, actions (all ^10)
  • ThemeProvider decorator for automatic light/dark mode switching
  • Custom scripts/generate-storybook-requires.js replaces sb-rn-get-stories to avoid Metro require.context crashes in Expo 52

Dependency Alignment with MetaMask Mobile:

Package MetaMask Mobile Our Storybook App Notes
expo ~52.0.47 ~52.0.49 Aligned
expo-font ~13.0.4 ~13.0.4 Aligned (14.x broke Android prebuild)
react 18.3.1 18.3.1 Aligned
react-native 0.76.9 0.76.9 Aligned
react-native-reanimated ^3.17.2 ~3.17.2 Pinned tighter (3.18+ requires RN 78+)
react-native-gesture-handler ^2.25.0 ^2.25.0 Aligned
react-native-safe-area-context ^5.4.0 ^5.4.0 Aligned
react-native-svg ^15.11.1 ^15.10.1 Close match
@react-native-async-storage/async-storage ^1.23.1 ^1.23.1 Aligned (was 2.x, downgraded to match)
@react-native-community/datetimepicker ^8.5.1 8.4.4 Close match

Build & Config Changes:

  • Removed hoistingLimits: "workspaces" — was causing dual-React copies in the monorepo, breaking hooks
  • Removed transform-inline-environment-variables babel plugin — conflicts with babel-preset-expo
  • Updated metro.config.js with withStorybook wrapper for SB10 Metro integration
  • Replaced metro-react-native-babel-preset with @react-native/babel-preset (RN 0.76 standard)
  • Updated Jest config transforms and mocks for RN 0.76 internals
  • Moved font assets to assets/fonts/ directory, added SemiBold variants
  • Removed ios/ from git tracking (generated by expo prebuild, already in .gitignore)
  • Added .rnstorybook/** to ESLint ignores (Metro-processed files)

Known Issues (documented in UPGRADE-STATUS.md)

  • BottomSheet stories: @gorhom/bottom-sheet has a "property is not writable" Metro compatibility issue affecting 2 stories. Other stories load fine.
  • Expo version warnings: Some resolved dep versions are newer than Expo 52 expects (aligned with Mobile instead). Warnings are non-blocking.

Related issues

Fixes: #843

Manual testing steps

First-time setup after pulling

yarn install
yarn workspace @metamask/storybook-react-native prestorybook

# iOS
yarn workspace @metamask/storybook-react-native exec expo run:ios --device "iPhone 15 Pro"

# Android
yarn workspace @metamask/storybook-react-native exec expo run:android

Note: Native rebuild is required once after pulling (native deps changed). Takes ~5-10 minutes per platform.

Day-to-day development

# iOS
yarn workspace @metamask/storybook-react-native exec expo start --dev-client --ios

# Android
yarn workspace @metamask/storybook-react-native exec expo start --dev-client --android

Verification steps

  1. Pull branch and run setup steps above
  2. Verify Storybook UI loads with story sidebar
  3. Navigate to Examples/WalletHome story — should render the full wallet mockup
  4. Navigate to component stories (Text, Box, Icon, etc.) — should render with controls
  5. Verify light/dark mode switching works (toggle device appearance)
  6. Run yarn test to verify no test regressions
  7. Run yarn lint to verify no lint errors

Screenshots/Recordings

After

Storybook v10 — full component showcase with on-device controls in android and ios

Screen.Recording.2026-04-16.at.1.02.23.PM.mov

Preview packages working in mobile in both Android and iOS

Screenshot 2026-04-17 at 12 06 27 PM
react.native.upgrade720.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

High Risk
High risk due to major upgrades of the React Native Storybook app (Storybook v10, Expo 52, RN 0.76.9, React 18.3.1) plus related Metro/Jest/Babel config changes that can break builds, bundling, or tests across the monorepo.

Overview
Upgrades the React Native Storybook app to Storybook v10 and migrates configuration/entrypoints from .storybook/ to .rnstorybook/, including a new view.getStorybookUI() bootstrap with AsyncStorage persistence and an updated decorator-based preview setup.

Aligns the Storybook RN runtime and several workspace packages to MetaMask Mobile versions (Expo 52, RN 0.76.9, React 18.3.1) and updates Metro integration (wraps config with withStorybook, keeps SVG transformer support). Also refreshes native app config (app.json identifiers, expo-font plugin, new architecture) and updates ignores for generated requires + ios//android/ prebuild outputs.

Modernizes RN package test/build tooling by switching DSRN test Babel preset to @react-native/babel-preset, updating Jest transforms/ignored modules, and adjusting reanimated/gesture-handler test setup; includes minor cleanup of lint suppressions in reanimated imports.

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

@socket-security
Copy link
Copy Markdown

socket-security bot commented Oct 21, 2025

@socket-security
Copy link
Copy Markdown

socket-security bot commented Oct 21, 2025

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

Ignoring alerts on:

  • babel-plugin-syntax-hermes-parser@0.23.1
  • babel-plugin-syntax-hermes-parser@0.25.1
  • @gorhom/bottom-sheet@5.2.9
  • @storybook/addon-ondevice-backgrounds@10.3.1
  • @storybook/addon-ondevice-notes@10.3.1
  • @react-native/babel-preset@0.76.9
  • @react-native/typescript-config@0.76.9
  • @expo/fingerprint@0.11.11
  • web-streams-polyfill@3.3.3
  • whatwg-url-without-unicode@8.0.0-3
  • @react-native/community-cli-plugin@0.76.9
  • react-native-is-edge-to-edge@1.1.7
  • @gorhom/portal@1.0.14
  • @storybook/react-native-ui-common@10.3.1
  • @storybook/react-native-ui@10.3.1
  • esbuild-register@3.6.0
  • react-native-url-polyfill@3.0.0
  • @react-native/babel-plugin-codegen@0.76.9
  • @jest/get-type@30.1.0
  • @jest/diff-sequences@30.0.1
  • @expo/ws-tunnel@1.0.6
  • @react-native/dev-middleware@0.76.9
  • resolve-workspace-root@2.0.0
  • @react-native/metro-babel-transformer@0.76.9
  • @babel/traverse--for-generate-function-map@7.28.4
  • @nozbe/microfuzz@1.0.0
  • es-toolkit@1.45.1
  • @expo/sudo-prompt@9.3.2
  • @isaacs/ttlcache@1.4.1
  • @react-native/debugger-frontend@0.76.9
  • chrome-launcher@0.15.2
  • chromium-edge-launcher@0.2.0
  • selfsigned@2.4.1
  • lightningcss-freebsd-x64@1.27.0
  • lightningcss-win32-arm64-msvc@1.27.0
  • lighthouse-logger@1.4.2
  • @types/node-forge@1.3.14
  • marky@1.3.0
  • picomatch@3.0.1
  • jest-matcher-utils@30.2.0
  • jest-diff@30.2.0
  • undici@6.22.0
  • react-refresh@0.14.2
  • webidl-conversions@5.0.0
  • @jest/schemas@30.0.5
  • @storybook/react-dom-shim@10.3.5
  • @storybook/mcp@0.6.2
  • valibot@1.3.1
  • @storybook/react@10.3.5
  • @sinclair/typebox@0.34.41
  • hermes-parser@0.25.1
  • hermes-parser@0.23.1
  • hermes-estree@0.25.1
  • hermes-estree@0.23.1
  • bplist-creator@0.0.7
  • pretty-format@30.2.0
  • commander@12.1.0
  • commander@14.0.3
  • ws@8.20.0
  • @expo/json-file@9.0.2
  • @expo/json-file@9.1.5
  • @expo/json-file@10.0.7
  • open@7.4.2
  • @babel/preset-typescript@7.27.1
  • react-native@0.76.9
  • dotenv@16.4.7
  • @react-native/assets-registry@0.76.9
  • @react-native/codegen@0.76.9
  • @react-native/gradle-plugin@0.76.9
  • @react-native/js-polyfills@0.76.9
  • @react-native/normalize-colors@0.76.9
  • @react-native/virtualized-lists@0.76.9
  • flow-enums-runtime@0.0.6
  • metro-runtime@0.81.5
  • metro-source-map@0.81.5
  • react-devtools-core@5.3.2
  • @babel/runtime@7.28.4
  • expo@52.0.49
  • expo-status-bar@2.0.1
  • react-native-reanimated@3.17.5
  • @react-native-async-storage/async-storage@1.24.0
  • @react-native-community/datetimepicker@8.6.0
  • @react-native-community/slider@4.5.7
  • @storybook/addon-ondevice-actions@10.3.1
  • @storybook/addon-ondevice-controls@10.3.1
  • @storybook/react-native@10.3.1
  • react-native-gesture-handler@2.25.0
  • react-native-safe-area-context@5.7.0
  • @babel/preset-react@7.27.1
  • @testing-library/react-native@13.3.3
  • react-native-svg@15.11.2
  • metro-symbolicate@0.81.5
  • ob1@0.81.5
  • get-intrinsic@1.3.0
  • @expo/cli@0.22.28
  • @expo/osascript@2.3.7
  • @expo/config@10.0.11
  • @expo/config-plugins@9.0.17
  • @expo/vector-icons@14.0.4
  • babel-preset-expo@12.0.12
  • expo-asset@11.0.5
  • expo-constants@17.0.8
  • expo-file-system@18.0.12
  • expo-font@13.0.4
  • expo-keep-awake@14.0.3
  • expo-modules-autolinking@2.0.8
  • expo-modules-core@2.2.3
  • babel-plugin-polyfill-corejs3@0.13.0
  • @storybook/react-native-theming@10.3.1
  • react-native-modal-datetime-picker@18.0.0
  • @babel/plugin-transform-async-generator-functions@7.28.0
  • @babel/plugin-transform-block-scoping@7.28.4
  • @babel/plugin-transform-destructuring@7.28.0
  • @babel/plugin-transform-export-namespace-from@7.27.1
  • @babel/plugin-transform-logical-assignment-operators@7.27.1
  • @babel/plugin-transform-numeric-separator@7.27.1
  • @babel/plugin-transform-object-rest-spread@7.28.4
  • @babel/plugin-transform-optional-catch-binding@7.27.1
  • @babel/plugin-transform-private-methods@7.27.1
  • @babel/plugin-transform-private-property-in-object@7.27.1
  • @babel/plugin-transform-regenerator@7.28.4
  • @babel/plugin-transform-spread@7.27.1
  • babel-plugin-polyfill-corejs2@0.4.14
  • babel-plugin-polyfill-regenerator@0.6.5
  • @babel/plugin-transform-react-jsx-development@7.27.1
  • @babel/plugin-transform-react-pure-annotations@7.27.1
  • @babel/plugin-proposal-export-default-from@7.27.1
  • @babel/plugin-syntax-export-default-from@7.27.1
  • @babel/plugin-syntax-flow@7.27.1
  • @babel/plugin-transform-flow-strip-types@7.27.1
  • @babel/plugin-transform-runtime@7.28.3
  • metro@0.81.5
  • metro-config@0.81.5
  • metro-core@0.81.5
  • metro-resolver@0.81.5
  • compression@1.8.1
  • @expo/code-signing-certificates@0.0.6
  • @expo/devcert@1.2.0
  • @expo/env@0.4.2
  • @expo/metro-config@0.19.12
  • @expo/package-manager@1.9.8
  • @expo/plist@0.2.2
  • @expo/prebuild-config@8.2.0
  • @urql/core@5.2.0
  • @urql/exchange-retry@1.3.2
  • node-forge@1.3.3
  • @expo/config-types@52.0.5
  • babel-plugin-react-native-web@0.19.13
  • dotenv-expand@11.0.7
  • dedent@1.7.2
  • metro-babel-transformer@0.81.5
  • metro-cache@0.81.5
  • metro-cache-key@0.81.5
  • metro-file-map@0.81.5
  • metro-transform-plugins@0.81.5
  • metro-transform-worker@0.81.5
  • on-headers@1.1.0
  • lightningcss@1.27.0
  • @expo/image-utils@0.6.5
  • @0no-co/graphql.web@1.2.0
  • metro-minify-terser@0.81.5
  • lightningcss-darwin-arm64@1.27.0
  • lightningcss-darwin-x64@1.27.0
  • lightningcss-linux-arm-gnueabihf@1.27.0
  • lightningcss-linux-arm64-gnu@1.27.0
  • lightningcss-linux-arm64-musl@1.27.0
  • lightningcss-linux-x64-gnu@1.27.0
  • lightningcss-linux-x64-musl@1.27.0
  • lightningcss-win32-x64-msvc@1.27.0

View full report

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Nov 7, 2025

📖 Storybook Preview

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall
Copy link
Copy Markdown
Contributor Author

@SocketSecurity ignore-all
These dependencies are all related to React Native and Expo, and are expected as part of the upgrade.

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/Icon/Icon.tsx Outdated
Comment thread packages/design-system-react-native/jest.config.js Outdated
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 2 potential issues.

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

Autofix Details

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

  • ✅ Fixed: Duplicate JSX transform from conflicting Babel presets
    • Removed '@babel/preset-react' and set '@react-native/babel-preset' jsxRuntime: 'automatic' to prevent duplicate JSX transforms.
  • ✅ Fixed: Missing reanimated setUpTests() call after removing mock
    • Added require('react-native-reanimated').setUpTests() in jest.setup.js to initialize Reanimated for Jest.

Create PR

Or push these changes by commenting:

@cursor push 884076eb43
Preview (884076eb43)
diff --git a/packages/design-system-react-native/babel.config.js b/packages/design-system-react-native/babel.config.js
--- a/packages/design-system-react-native/babel.config.js
+++ b/packages/design-system-react-native/babel.config.js
@@ -2,11 +2,10 @@
   env: {
     test: {
       presets: [
-        '@react-native/babel-preset',
         [
-          '@babel/preset-react',
+          '@react-native/babel-preset',
           {
-            runtime: 'automatic',
+            jsxRuntime: 'automatic',
           },
         ],
         [

diff --git a/packages/design-system-react-native/jest.setup.js b/packages/design-system-react-native/jest.setup.js
--- a/packages/design-system-react-native/jest.setup.js
+++ b/packages/design-system-react-native/jest.setup.js
@@ -1,3 +1,5 @@
+require('react-native-reanimated').setUpTests();
+
 jest.mock('react-native-svg', () => {
   const React = require('react');
   const { View } = require('react-native');

Comment thread packages/design-system-react-native/babel.config.js
Comment thread packages/design-system-react-native/jest.setup.js
@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 5 total unresolved issues (including 4 from previous reviews).

Autofix Details

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

  • ✅ Fixed: Published package peer dependency pinned to exact React version
    • Changed @metamask/design-system-twrnc-preset peerDependencies.react from "18.3.1" to the range ">=18.2.0" to match other packages and avoid strict pinning.

Create PR

Or push these changes by commenting:

@cursor push 4e1d02e2a7
Preview (4e1d02e2a7)
diff --git a/packages/design-system-twrnc-preset/package.json b/packages/design-system-twrnc-preset/package.json
--- a/packages/design-system-twrnc-preset/package.json
+++ b/packages/design-system-twrnc-preset/package.json
@@ -81,7 +81,7 @@
   },
   "peerDependencies": {
     "@metamask/design-tokens": "^8.0.0",
-    "react": "18.3.1"
+    "react": ">=18.2.0"
   },
   "engines": {
     "node": "^18.18 || >=20"

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

Comment thread packages/design-system-twrnc-preset/package.json Outdated
@georgewrmarshall georgewrmarshall changed the title chore: upgrade React Native from 0.72.15 to 0.76.9 with babel configuration updates chore: upgrade React Native Storybook to v10 and align deps with MetaMask Mobile Apr 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 2 potential issues.

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

Autofix Details

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

  • ✅ Fixed: Script finds zero stories due to glob path bug
    • Adjusted base directory extraction to strip '**' from glob patterns so 'find' searches real directories and discovers stories.
  • ✅ Fixed: GestureHandlerRootView wrapper removed from Storybook decorator
    • Restored GestureHandlerRootView wrapper in preview decorator to enable gesture handling.

Create PR

Or push these changes by commenting:

@cursor push b360e425fd
Preview (b360e425fd)
diff --git a/apps/storybook-react-native/.rnstorybook/preview.js b/apps/storybook-react-native/.rnstorybook/preview.js
--- a/apps/storybook-react-native/.rnstorybook/preview.js
+++ b/apps/storybook-react-native/.rnstorybook/preview.js
@@ -1,5 +1,6 @@
 import React from 'react';
 import { useColorScheme } from 'react-native';
+import { GestureHandlerRootView } from 'react-native-gesture-handler';
 import { ThemeProvider, Theme } from '@metamask/design-system-twrnc-preset';
 
 const ThemeDecorator = ({ children }) => {
@@ -7,9 +8,11 @@
   const theme = colorScheme === 'dark' ? Theme.Dark : Theme.Light;
 
   return (
-    <ThemeProvider theme={theme}>
-      {children}
-    </ThemeProvider>
+    <GestureHandlerRootView style={{ flex: 1 }}>
+      <ThemeProvider theme={theme}>
+        {children}
+      </ThemeProvider>
+    </GestureHandlerRootView>
   );
 };
 

diff --git a/apps/storybook-react-native/scripts/generate-storybook-requires.js b/apps/storybook-react-native/scripts/generate-storybook-requires.js
--- a/apps/storybook-react-native/scripts/generate-storybook-requires.js
+++ b/apps/storybook-react-native/scripts/generate-storybook-requires.js
@@ -28,7 +28,19 @@
  * @returns {string[]} Matching file paths relative to rnstorybookDir.
  */
 function findStoryFiles(pattern, cwd) {
-  const resolvedBase = path.resolve(cwd, path.dirname(pattern));
+  // Derive a real base directory from the glob pattern.
+  // path.dirname on a pattern with "**" yields a non-existent "src/**" folder.
+  // Strip "**" and everything after it to get the actual base directory.
+  let baseFromPattern = pattern;
+  const recursiveIdx = baseFromPattern.indexOf('**');
+  if (recursiveIdx !== -1) {
+    baseFromPattern = baseFromPattern.slice(0, recursiveIdx);
+  } else {
+    baseFromPattern = path.dirname(baseFromPattern);
+  }
+  // Remove any trailing path separators left after slicing
+  baseFromPattern = baseFromPattern.replace(/[\\/]+$/u, '') || '.';
+  const resolvedBase = path.resolve(cwd, baseFromPattern);
 
   // Extract extensions from @(js|jsx|ts|tsx) pattern
   const extMatch = pattern.match(/@\(([^)]+)\)/u);

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

Comment thread apps/storybook-react-native/scripts/generate-storybook-requires.js Outdated
Comment thread apps/storybook-react-native/.rnstorybook/preview.tsx
@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 4 total unresolved issues (including 3 from previous reviews).

Autofix Details

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

  • ✅ Fixed: Pinned react version mismatches react-dom range
    • Pinned react-dom to 18.3.1 in both Storybook apps to match the pinned react version.

Create PR

Or push these changes by commenting:

@cursor push 556c18b76a
Preview (556c18b76a)
diff --git a/apps/storybook-react-native/package.json b/apps/storybook-react-native/package.json
--- a/apps/storybook-react-native/package.json
+++ b/apps/storybook-react-native/package.json
@@ -39,7 +39,7 @@
     "@storybook/react-native": "^10",
     "@types/react": "^18.2.0",
     "@types/react-dom": "^18.2.0",
-    "react-dom": "^18.2.0",
+    "react-dom": "18.3.1",
     "react-native-safe-area-context": "^5.4.0",
     "react-native-svg": "^15.11.1",
     "react-native-svg-transformer": "^1.5.0",

diff --git a/apps/storybook-react/package.json b/apps/storybook-react/package.json
--- a/apps/storybook-react/package.json
+++ b/apps/storybook-react/package.json
@@ -36,7 +36,7 @@
     "postcss": "^8.4.47",
     "prop-types": "^15.8.1",
     "react": "18.3.1",
-    "react-dom": "^18.2.0",
+    "react-dom": "18.3.1",
     "storybook": "^10.3.1",
     "tailwindcss": "^3.0.0",
     "typescript": "~5.2.2",

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

Comment thread apps/storybook-react/package.json
@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

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 4 total unresolved issues (including 3 from previous reviews).

Autofix Details

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

  • ✅ Fixed: Mismatched useJs setting between Metro and prestorybook script
    • Set useJs: true in apps/storybook-react-native/metro.config.js to align with prestorybook’s --use-js generation and avoid TS/JS mismatch.

Create PR

Or push these changes by commenting:

@cursor push cc6e2767ea
Preview (cc6e2767ea)
diff --git a/apps/storybook-react-native/metro.config.js b/apps/storybook-react-native/metro.config.js
--- a/apps/storybook-react-native/metro.config.js
+++ b/apps/storybook-react-native/metro.config.js
@@ -24,4 +24,5 @@
 
 module.exports = withStorybook(defaultConfig, {
   enabled: true,
+  useJs: true,
 });

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

Comment thread apps/storybook-react-native/metro.config.js Outdated
@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall
Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

georgewrmarshall added a commit that referenced this pull request Apr 16, 2026
## **Description**

Cherry-picks the React Native `Icon` type fix out of
[#844](#844) into
a focused PR.

This updates `IconProps` to align with `react-native-svg`
(`Omit<SvgProps, 'color' | 'name'>` instead of `ViewProps`) and keeps
`hitSlop` forwarding type-safe in `Icon.tsx`.

Also adds migration guidance in
`packages/design-system-react-native/MIGRATION.md` for consumers that
were passing `View`-specific props to `Icon`.

## **Related issues**

Fixes:

## **Manual testing steps**

1. Pull this branch.
2. Open
`packages/design-system-react-native/src/components/Icon/Icon.types.ts`
and confirm `IconProps` extends `Omit<SvgProps, 'color' | 'name'>`.
3. Open
`packages/design-system-react-native/src/components/Icon/Icon.tsx` and
confirm `hitSlop` is forwarded as `hitSlop ?? undefined`.
4. Open `packages/design-system-react-native/MIGRATION.md` and confirm
the new Icon migration note under `From version 0.18.0 to 0.19.0`.

## **Screenshots/Recordings**

N/A (type-only + docs update)

### **Before**

N/A

### **After**

N/A

## **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
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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**
> Mostly a type-surface change, but it can break TypeScript builds for
consumers passing `ViewProps` (e.g., `onLayout`, `testID`) directly to
`Icon` and may require small refactors.
> 
> **Overview**
> Aligns the React Native `Icon` API surface with `react-native-svg` by
changing `IconProps` to extend `Omit<SvgProps, 'color' | 'name'>`
(instead of `ViewProps`), which removes `View`-specific props from the
`Icon` type.
> 
> Updates `Icon` to destructure and forward `hitSlop` as `hitSlop ??
undefined` for stricter SVG typing, and documents the type-breaking
migration path in `MIGRATION.md` (wrap `Icon` in a `View` for
layout/view props).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
14817d4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@github-actions
Copy link
Copy Markdown
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/design-system-react": "0.17.0-preview.ba86146",
  "@metamask-previews/design-system-react-native": "0.18.0-preview.ba86146",
  "@metamask-previews/design-system-shared": "0.11.0-preview.ba86146",
  "@metamask-previews/design-system-tailwind-preset": "0.6.1-preview.ba86146",
  "@metamask-previews/design-system-twrnc-preset": "0.4.1-preview.ba86146",
  "@metamask-previews/design-tokens": "8.3.0-preview.ba86146"
}

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

},
};
})();
const defaultConfig = getDefaultConfig(__dirname);
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 starts from Expo default Metro config rather than rebuilding resolver settings by hand, which keeps the app aligned with Expo monorepo-aware defaults for watch folders and workspace module resolution. That matches the Storybook guidance to wrap an existing Metro config instead of replacing it: https://storybookjs.github.io/react-native/docs/intro/configuration/metro-configuration/

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

"expo-system-ui": "~2.4.0",
"react-native-reanimated": "~3.3.0",
"uuid": "^3.0.0"
"expo": "~52.0.49",
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 dependency block is intentionally split so the app owns the native runtime pieces it actually boots with: Expo, React Native, React, gesture-handler, and reanimated stay aligned with Mobile, while Storybook v10 and its on-device addons live in devDependencies as tooling. That keeps Yarn constraints happy, avoids relying on root-hoisted native modules, and makes this app a realistic client for validating @metamask/design-system-react-native behavior.

Comment thread apps/storybook-react-native/package.json Outdated

module.exports = {
assets: [path.resolve(__dirname, '../assets/fonts')],
assets: [path.resolve(__dirname, 'fonts')],
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.

Looks like this was always wrong?

"expo-system-ui": "~2.4.0",
"react-native-reanimated": "~3.3.0",
"uuid": "^3.0.0"
"expo": "~52.0.49",
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.

These runtime dependencies now describe the actual native environment the app boots with instead of depending on root hoists or stale Expo 49-era transitive installs. Keeping Expo, React, React Native, gesture-handler, and reanimated aligned here makes this app a realistic client for validating design-system-react-native against the same compatibility floor Mobile is targeting.

"@storybook/addon-ondevice-actions": "6.5",
"@storybook/addon-ondevice-controls": "6.5",
"@storybook/react-native": "6.5",
"@babel/core": "^7.25.2",
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 devDependency block is now clearly the Storybook/tooling layer: Storybook v10 packages, SVG transform support, and test/build helpers live here while the app runtime stays in dependencies. That split matters because this workspace is an app, not a published library, so reviewers can read this file as runtime surface versus local development surface.

"peerDependencies": {
"react": "^18.2.0",
"react-native": "0.72.15",
"react-native-gesture-handler": "~2.12.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.

Dropping peerDependencies makes this manifest read like a private app again instead of a consumable package. The compatibility contract belongs on @metamask/design-system-react-native; this app should pin the concrete versions it runs and test against, not ask an external consumer to provide them.

"dependenciesMeta": {
"uuid": {}
},
"peerDependencies": {
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 dependenciesMeta for uuid is part of the same cleanup: uuid is no longer part of the Storybook runtime path, so the app no longer needs package-manager hints to special-case it. That keeps the manifest focused on the modules this native client actually uses after the Storybook v10 migration.

@@ -35,8 +35,8 @@
"playwright": "^1.52.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.

Aligns deps and passes yarn constraints

PanGestureHandler,
PanGestureHandlerGestureEvent,
} from 'react-native-gesture-handler';
// eslint-disable-next-line import-x/default
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 unused eslint disable comment

} from 'react';
import { Dimensions, View } from 'react-native';
import type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
// eslint-disable-next-line import-x/default
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 unused eslint disable comment

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

"deepmerge": "^4.2.2",
"jest": "^29.7.0",
"react": "^18.2.0",
"react": "18.3.1",
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.

Aligns deps and passes yarn constraints

"jest": "^29.7.0",
"postcss": "^8.4.47",
"react": "^18.2.0",
"react": "18.3.1",
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.

Aligns deps and passes yarn constraints

},
transformIgnorePatterns: [
'node_modules/(?!react-native|@react-native|react-native-reanimated|@react-navigation)',
'node_modules/(?!(react-native|@react-native|react-native-reanimated|@react-navigation|react-native-jazzicon|react-native-gesture-handler|react-native-safe-area-context)/)',
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.

react-native-safe-area-context is included in transformIgnorePatterns because its official Jest mock is distributed from the package and needs Babel/Jest to transpile it in node_modules. This follows the safe-area testing guidance here: https://appandflow.github.io/react-native-safe-area-context/testing/

'\\.(css|less|scss)$': 'identity-obj-proxy',
'\\.svg$': '<rootDir>/__mocks__/svgMock.js',
},
setupFiles: ['react-native-gesture-handler/jestSetup'],
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.

react-native-gesture-handler/jestSetup keeps the Jest environment aligned with Gesture Handler's supported test setup instead of relying on ad hoc mocks in component tests. Upstream guidance is here: https://docs.swmansion.com/react-native-gesture-handler/docs/guides/testing/

@@ -1,5 +1,4 @@
// Import built-in Jest matchers from React Native Testing Library
import '@testing-library/react-native/extend-expect';
require('react-native-reanimated').setUpTests();
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.

Reanimated now uses setUpTests() from the library itself, which is the supported way to initialize its Jest environment after the RN upgrade. That keeps animation-related assumptions centralized in upstream setup instead of maintaining a custom global mock here: https://docs.swmansion.com/react-native-reanimated/docs/guides/testing/

// Silence warnings related to the Animated API
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

jest.mock(
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 suite now uses react-native-safe-area-context's official Jest mock and then reapplies zero insets/frame defaults before each test because some specs override the module state at runtime. That keeps the baseline deterministic while still following the library's documented mock entrypoint: https://appandflow.github.io/react-native-safe-area-context/testing/

Comment thread package.json
@@ -117,13 +117,10 @@
"lodash": "^4.17.21",
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.

react, react-native, and twrnc are removed from the root devDependencies because Storybook React Native now declares and resolves its own runtime stack inside the app workspace instead of relying on hoisted fallbacks. That keeps the monorepo aligned with Yarn constraints and avoids masking missing app-level dependencies behind the root package.json.

Comment thread eslint.config.mjs
'apps/storybook-react/tailwind.config.js',
// storybook react native
'apps/storybook-react-native/.storybook/**/*.js',
'apps/storybook-react-native/.rnstorybook/**',
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 React Native app now generates and owns its config under .rnstorybook, so the old .storybook ignore was replaced instead of expanded. That also leaves .storybook available for a future web Storybook setup, which matches the Storybook template split between .rnstorybook and .storybook: https://github.com/dannyhw/expo-template-storybook

@georgewrmarshall georgewrmarshall self-assigned this Apr 17, 2026
@georgewrmarshall georgewrmarshall enabled auto-merge (squash) April 17, 2026 22:10
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.

1 participant