Skip to content

Redesign DevLoadingView (iOS) - #58866

Open
huntie wants to merge 1 commit into
mainfrom
pr58866
Open

huntie wants to merge 1 commit into
mainfrom
pr58866

Conversation

@huntie

@huntie huntie commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The dev loading banner spans the full width under the status bar. On iPhone Duo it collides with the rail and camera cutout, and it straddles the hinge when the device is partly folded.

On top of wider out-of-tree platform support since it was created (desktop, iPad, visionOS and more), this UI component was due a visual refresh.

Before After
file-8526fc34d7d27af5e921cf27668a089e image

This diff

Redesigns <DevLoadingView> as a floating pill at the center-top of the screen.

Key changes:

  • New shape, rendered as Liquid Glass on iOS 26+, a solid fill below.
  • Passes touches outside the capsule through to the app.
  • More subtle scale and fade animation (same timings as before).

iPhone Duo platform nuances:

  • Handles left/right safe area (when needed) on iPhone Duo.
  • Handles iPhone Duo Preferred Placement: moves into the left panel when the hinge settles partly open.
  • Device specific centring, and safe area tweaks for various poses (see Test Plan).

Why so much attention?

These updates + details help reinforce that React Native is maintained and high quality, and supports the iOS platform completely. Delighting the user (e.g. avoiding the iPhone Duo hinge like other system elements) is a goal.

Changelog:
[iOS][Changed] - Dev loading banner: Redesign in-app Loading/Fast Refresh banner

Test Plan

cd packages/rn-tester
bundle exec pod install
xcodebuild -workspace RNTesterPods.xcworkspace -scheme RNTester -configuration Debug -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' build

App states, iPhone 18 Pro

Note: This is RNTester's non-native header — regular headers sit a bit lower and generally align a bit better with the loading view vertically.

Light Dark
Loading
Fast Refresh
Disconnected

Disconnected

(Largest existing variant, stays visible until dismissed)

iPhone 18 Pro iPhone Duo, folded iPhone Duo, unfolded iPhone Duo, unfolded, portrait
✅ Aligned system center (also applies in 2-app splits)

🎬 End to end app load, Fast Refresh

ios-pill-e2e-load-refresh-3.mov

🎬 Dynamic fold avoidance, iPhone Duo

Screen.Recording.2026-10-05.at.20.50.31.mov
  • ✅ Folding moves the capsule into the left panel once the hinge settles, and unfolding recenters it.
  • ⚠️ Not run: the solid fill below iOS 26, the path without hinge APIs below iOS 27.1, and Split View since the alert-matched centering.

@huntie
huntie added this pull request to stack #58868 October 5, 2026 16:11
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 5, 2026
@huntie huntie changed the title Redesign DevLoadingView as a floating capsule (iOS) [WIP DRAFT] Redesign DevLoadingView (iOS) Oct 5, 2026
@huntie huntie changed the title [WIP DRAFT] Redesign DevLoadingView (iOS) Redesign DevLoadingView (iOS) Oct 5, 2026
@huntie
huntie marked this pull request as ready for review October 5, 2026 21:00
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 5, 2026

@cipolleschi cipolleschi 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.

left some questions and nits

// UIAlertController on iOS 27.1.
static CGFloat RCTDevLoadingViewAlertCenterOffset(UIEdgeInsets safeAreaInsets)
{
return 0.2818 * (safeAreaInsets.left - safeAreaInsets.right) / 2;

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.

what is this number?? it is oddly specific! xD
Also, safeAreaInsets.left - safeAreaInsets.right in most case will end up being 0... Problably only for the Duo it does return something that is not 0.

Comment on lines +131 to +133
#if RCT_DEV_LOADING_VIEW_HAS_HINGE
[_divisionPollTimer invalidate];
#endif

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.

why we need this only for the Duo?

Comment on lines +219 to +221
((RCTDevLoadingWindow *)self->_window).layoutHandler = ^{
[weakSelf _updatePlacementAnimated:NO];
};

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.

rather then this ugly casting.. can we create the right window in a variable at line 211:

RCTDevLoadingWindow * devLoadingWindow = windowScene != nil ? [[RCTDevLoadingWindow alloc] initWithWindowScene:windowScene]
                                         : [[RCTDevLoadingWindow alloc] init];
self->_window = devLoadingWindow

so that here we only have to:

devLoadingWindow.layoutHandler = ^{
  [weakSelf _updatePlacementAnimated:NO];
};

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants