Repository navigation
fix: measureInWindow calculations for Modal with formSheet presentation - #59098
Open
kirillzyusko wants to merge 3 commits into
Open
kirillzyusko wants to merge 3 commits into
kirillzyusko wants to merge 3 commits into
Conversation
kirillzyusko
force-pushed
the
fix/use-window-dimensions-in-form-sheet-modal-on-ios
branch
from
October 15, 2026 11:13
042dfcb to
eb9d254
Compare
This branch has not been deployed
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:
Coming from #56062 but after fork re-sync
Fixed
measureInWindowcalculations forModalwithformSheetpresentation.This is only Fabric problem (paper works well because it relies on UIKit implementation).
Problem
The core issue is in how
measureInWindowworks differently between Paper and Fabric.Paper calls iOS native
[view.window convertRect:view.frame fromView:view.superview]which uses UIKit's actual view hierarchy. When aformSheetmodal is presented, the modal's view controller lives in a separateUIWindowor has a known offset from the top of the screen. UIKit'sconvertRect:fromView:correctly accounts for this because it works with the real rendered view positions.Fabric's
measureInWindow(inDOM.cpp) works entirely in the shadow tree, not the native view hierarchy. It callsgetLayoutMetricsFromRootwhich walks up the shadow node ancestors accumulating frame origins. The critical logic is atLayoutableShadowNode.cpp:auto shouldApplyTransformation = (policy.includeTransform && !isRootNode) || (policy.includeViewportOffset && isRootNode);The
includeViewportOffsetflag only applies the root node's transform. For aformSheetmodal, the Y offset from the top of the screen (the ~62pt gap where the modal doesn't cover the full screen) would need to be represented as a transform on the root shadow node. But the modal's screen position is a UIKit concern — it's theUIViewControllerpresentation that positions the modal content on screen, not a shadow tree transform.The key is at
ModalHostViewShadowNode.h:The
ModalHostViewShadowNodehas theRootNodeKindtrait. This means whencomputeRelativeLayoutMetricswalks up from the view, it stops at the modal node (seeLayoutableShadowNode.cpp):Then at the "apply transform" step:
auto shouldApplyTransformation = (policy.includeTransform && !isRootNode) || (policy.includeViewportOffset && isRootNode);For the Modal's root node,
includeViewportOffset && isRootNodeistrue, so it appliesgetTransform(). ButModalHostViewShadowNodedoesn't overridegetTransform()— onlyRootShadowNodedoes (which translates byviewportOffset). The defaultgetTransform()returnsTransform::Identity().So the modal's screen position (the formSheet top inset) is simply never encoded anywhere in the shadow tree.
Solution
The fix is in
RCTModalHostViewComponentView.mm. InboundsDidChange, when the modal's bounds change, the state is updated with just the size:The fix needs to:
ModalHostViewStateto include aviewportOffset(the modal's origin on screen)boundsDidChangecompute the modal view controller's actual screen position (e.g.,self.viewController.view.frame.originin window coordinates) and pass it as the viewport offsetgetTransform()onModalHostViewShadowNodeto apply the viewport offset from state.This way, when
measureInWindowwalks up to the modal (which is aRootNodeKind),includeViewportOffsettriggersgetTransform(), which now returns the actual screen offset instead of identity.Changelog:
[IOS] [FIXED]
measureInWindowcalculations forModalwithformSheetpresentationTest Plan:
I used this code in RNTester:
Click to expand
If you press on a red rectangle with a fix you will see a correct
y=72(10pt padding in container + 62pt safe area padding):Without a fix the
y=10(which is incorrect).