feat!: bump Expo SDK 52 -> 55 (requires Reanimated 4)#161
Merged
Conversation
Coordinated upgrade replacing 10 individual Renovate PRs that were each blocked by Expo SDK 52's pinned versions. kitchen-sink (examples): - expo ^52.0.16 -> ^55.0.24 - react 18.3.1 -> 19.2.0 - react-dom 18.3.1 -> 19.2.0 - react-native 0.76.9 -> 0.83.6 - expo-constants, expo-linking, expo-router, expo-splash-screen, expo-status-bar -> SDK 55 line - react-native-gesture-handler 2.20.2 -> ~2.30.0 - react-native-reanimated ~3.16.5 -> 4.3.1 - react-native-safe-area-context 4.12.0 -> ~5.6.2 - react-native-screens ~4.4.0 -> ~4.23.0 - react-native-web ~0.19.13 -> ^0.21.0 modal (library devDeps only; peers stay `*`): - @types/react, react-native, jest-expo, react-test-renderer, @testing-library/react-native bumped to match workspace Other: - Drop `newArchEnabled` from app.config.ts (default in SDK 55) - Adjust metro.config.js for tightened Metro `Readonly` config types - Exclude `dist` from packages/modal tsconfig (fixes typecheck/build race) - Pin reanimated to 4.3.1 (Expo SDK 55 advises 4.2.1 but its compatibility.json rejects worklets 0.8.x, breaking pod install). Added expo.install.exclude for reanimated to silence doctor. Verified: expo-doctor 15/15, typecheck 4/4, modal builds clean, iOS xcodebuild succeeds, app launches in iPhone 17 Pro sim.
Adds end-to-end coverage so dep bumps and SDK upgrades like this one catch runtime breakage that typecheck/lint/expo-doctor miss. - examples/kitchen-sink/.maestro/smoke-launch.yaml: launch + assert home - examples/kitchen-sink/.maestro/smoke-modal-open-close.yaml: open primary modal, dismiss via Close Modal, assert return - .github/workflows/e2e-ios.yml: macos-14 runner, prebuild + Release build + Maestro CLI; uploads debug output as artifact on failure - Brings forward the user's crash-test/issue155/stress-test flows for local use; NOT run on CI (they require the issue-155 fix branch) - .maestro/README.md documents which flows run where
@react-native/metro-config@0.85.3 (transitive of community-cli-plugin) was pulling metro@0.84.4 on fresh installs, failing expo-doctor's native-module compatibility check (SDK 55 ships @expo/metro requiring metro@^0.83.3). Local installs masked this via stale node_modules; CI caught it.
typescript-eslint v8 errors when both options are set. Also moves the kitchen-sink ScrollView import to react-native (gesture-handler ScrollView was flagged by no-restricted-syntax), and applies prettier to the new .maestro/README.md.
Reanimated 4 deprecates `runOnJS` in favor of `scheduleOnRN` from `react-native-worklets`. ESLint v4 flags the deprecation as an error. Declares react-native-worklets as an optional peer of the modal library since it ships transitively with Reanimated 4 already.
Two SDK 55 blockers found via runtime + CI testing: 1. pnpm resolved @expo/metro-runtime to 4.0.0 (the SDK 52 version) even though expo-router@55 requires ^55.0.11. The stale 4.0.0 ships a broken messageSocket.native.ts that calls `getDevServer()` directly on a CJS module namespace, throwing "TypeError: getDevServer is not a function (it is Object)" at JS bootstrap. Adding @expo/metro-runtime as a direct dep of the kitchen-sink (and pinning it via pnpm.overrides) forces 55.0.11, which removes the broken file entirely. 2. expo-modules-core 55.0.25 doesn't compile under Xcode 16's Swift 6 complete-mode strict concurrency (MainActor/Sendable errors). Upstream fix (PR #44141) is unmerged. Adds an Expo config plugin that injects a post_integrate hook lowering SWIFT_STRICT_CONCURRENCY to `targeted` only for the ExpoModulesCore pod. Verified: expo-doctor 15/15, typecheck 4/4, prebuild injects the hook, pod install succeeds.
- Add JSDoc ConfigPlugin type so the JS plugin passes tsc strict mode - Use extendedWaitUntil + waitForAnimationToEnd in smoke flows to give iOS 26.5's reworked accessibility tree time to settle before maestro queries it (iOS 26 changed when XCUITest exposes RN Text nodes)
Sets minimum peer versions to reflect what the library actually requires after the runOnJS -> scheduleOnRN migration. Existing consumers on older RN/Reanimated will get an install warning instead of a confusing runtime error. BREAKING CHANGE: react-native-reanimated >=4.0.0 is now required. Other peers bumped to the versions Reanimated 4 itself requires: - react >=18.0.0 - react-native >=0.81.0 - react-native-gesture-handler >=2.20.0 - react-native-worklets >=0.5.0 (optional, ships with Reanimated 4)
5 tasks
GSTJ
added a commit
that referenced
this pull request
May 19, 2026
## Summary Three post-merge regressions introduced by #161: 1. **`🚀 Publish` failed** — `turbo release` fanned out to `packages/eslint-config` which tried to npm-publish without auth. Result: `react-native-magic-modal@7.0.0` did NOT ship. Fixed by scoping the workspace `release` script to `--filter=react-native-magic-modal`. 2. **`📚 Docs` failed** — `pnpm run docs --force` doesn't pass through to turbo cleanly; turbo errors with `unexpected argument '--force'`. Fixed by adding `--` so the flag reaches turbo's command target. 3. **`📱 E2E iOS` failed** — macos-15's default Xcode is 16.4 (Swift 6.0) but `expo-modules-core@55.x` uses `@MainActor` extension attribute syntax that requires Swift 6.1+ (Xcode 16.5 / Xcode 26). Adds a workflow step that selects an Xcode 26 install if present. The Podfile config plugin from #161 still helps as a fallback (lowers strict concurrency for the ExpoModulesCore pod), so it stays. ## Once this merges Re-trigger the `🚀 Publish` workflow on `main` (or push an empty commit) to ship `react-native-magic-modal@7.0.0` to npm. Doing it explicitly after this lands so the publish goes through with the scope fix. ## Test plan - [x] `pnpm typecheck` → 4/4 - [x] `pnpm lint` → 3/3 - [ ] `🛠️ Branch Checkup` passes - [ ] `📚 Docs` passes - [ ] `📱 E2E iOS (Maestro)` passes (Xcode 26 fix)
This was referenced May 19, 2026
Merged
GSTJ
added a commit
that referenced
this pull request
May 19, 2026
## Summary - Bumps `react-native-magic-modal` from `6.0.6` to `7.0.0` - Renames the `Unreleased` heading in `CHANGELOG.md` to `7.0.0 (2026-05-19)` - Captures the Expo SDK 52 -> 55 breaking peer-dep bumps (RN 0.83, React 19, Reanimated 4, worklets 0.5) from #161 that earlier failed publish runs lost track of. ## Why a manual bump? The original `feat!: bump Expo SDK 52 -> 55` lived in the squashed history of #161, but the most recent commits on `main` are `ci(release):` / `chore:` style, so release-it's conventional-changelog plugin computed a `patch` (6.0.6 → 6.0.7). This PR pre-stamps `7.0.0` so the next publish workflow run picks it up verbatim. Intentionally **no** `feat!:` / `BREAKING CHANGE:` marker on the commit — that would cause release-it to compound the bump again. ## Test plan - [x] `package.json` version reads `7.0.0` - [x] `CHANGELOG.md` top section is `## 7.0.0 (2026-05-19)` with the BREAKING CHANGES intact - [ ] Branch checks pass - [ ] After merge, Publish workflow ships `7.0.0` (gated on `NPM_TOKEN` rotation — see follow-up issue)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Coordinated Expo SDK 52 → 55 upgrade for the kitchen-sink example, with the library's peer dependency floors raised to match Reanimated 4's ecosystem requirements. Replaces 10 stalled Renovate PRs (#128, #129, #130, #132, #134, #148, #150, #151, #152, #154) that were each blocked by SDK 52's pinned versions.
Library minimum peer versions are now:
react>=18.0.0react-native>=0.81.0react-native-gesture-handler>=2.20.0react-native-reanimated>=4.0.0react-native-worklets>=0.5.0(optional; ships with Reanimated 4)The deprecated
runOnJSfromreact-native-reanimatedwas replaced withscheduleOnRNfromreact-native-worklets, which only exists in Reanimated 4. Consumers on Reanimated 3 or earlier must upgrade.packages/modal/CHANGELOG.mdhas an Unreleased entry under "⚠ BREAKING CHANGES" with the same list.What changed
examples/kitchen-sink(playground)expo^52.0.16→^55.0.24react/react-dom18.3.1→19.2.0react-native0.76.9→0.83.6expo-constants,expo-linking,expo-router,expo-splash-screen,expo-status-bar→ SDK 55 linereact-native-gesture-handler2.20.2→~2.30.0react-native-reanimated~3.16.5→4.3.1react-native-safe-area-context4.12.0→~5.6.2react-native-screens~4.4.0→~4.23.0react-native-web~0.19.13→^0.21.0@expo/metro-runtime~55.0.11direct dep +pnpm.overridespin (was stuck on 4.0.0 via stale resolution, causinggetDevServer is not a functionat JS bootstrap)expo.install.excludeforreact-native-reanimated(Expo SDK 55 advises 4.2.1 but its bundled compatibility.json rejects worklets 0.8.x; 4.3.1 is the authoritative fix)newArchEnabledfromapp.config.ts(default in SDK 55)metro.config.jsfor SDK 55's tightenedReadonlyMetro config typesplugins/withExpoModulesCoreSwiftStrictConcurrency.js: lowersSWIFT_STRICT_CONCURRENCY=targetedfor the ExpoModulesCore pod only, working around fix(expo-modules-core): Swift 6 / Xcode 16 strict concurrency compliance expo/expo#44141 (Xcode 16 Swift 6 strict mode)packages/modal(library)runOnJSwithscheduleOnRNfromreact-native-workletsreact-native-workletsas optional peer@types/react19,react-native0.83.6,jest-expo55,react-test-renderer19,@testing-library/react-native13.3)distfromtsconfig.json(fixes typecheck/build race with bunchee)Tooling
metro@^0.83.3viapnpm.overrides(was pulling 0.84.4 from@react-native/community-cli-plugin, failing expo-doctor)parserOptions.project(superseded byprojectServicein typescript-eslint v8; fixes lint parse errors)ScrollViewimport fromreact-native-gesture-handlerin kitchen-sink (use core RN to satisfyno-restricted-syntax)CI
.github/workflows/e2e-ios.yml:macos-15runner, full prebuild + Release iOS build + Maestro smoke flows, uploads Maestro debug output as artifact on failureexamples/kitchen-sink/.maestro/:smoke-launch.yamlandsmoke-modal-open-close.yaml(run on CI; hardened withextendedWaitUntil+waitForAnimationToEndfor iOS 26 accessibility timing)crash-test-dropdown.yaml,issue155-crash-test.yaml,stress-test-crash.yamlare brought forward for local use (they reference screens that only exist on thefix/issue-155-navigation-crashbranch, so not in CI matrix)README.mddocumenting which flow runs whereTest plan
pnpm installclean (nonode_modulespatches required)pnpm --filter @magic/kitchen-sink doctor→ 15/15pnpm typecheck→ 4/4pnpm lint→ 3/3pnpm --filter react-native-magic-modal build→ cleanexpo prebuild --platform ios --clean+expo run:ioson iPhone 17 Pro (iOS 26.5) → BUILD SUCCEEDED, kitchen-sink home screen renders with all 9 modal buttons (screenshot verified)🛠️ Branch Checkupgreen (in progress)📱 E2E iOS (Maestro)green (in progress)