Skip to content

iOS dim renders in wrong UIWindow when sheet is presented from a detached UIViewController #661

@kanzelm3

Description

@kanzelm3

Before submitting a new issue

  • I tested using the latest version of the library.
  • I tested using a supported version of React Native.
  • I checked for existing issues that might answer my question.

Bug Summary

On iOS, when a TrueSheet is presented from a UIViewController that is not reachable from the key window's root VC via the parent / presentingViewController chain (i.e. "detached" in UIKit's terms), the sheet content itself renders correctly, but UIKit's UISheetPresentationController dim layer ends up in the wrong UIWindow. The net visual effect is that the sheet is visible but appears over undimmed content, while the dim lives behind whatever UIKit chose as the fallback container.

iOS itself surfaces this at runtime:

[UIKitCore] Presenting view controller <TrueSheetViewController: …> from detached view controller <RCTFabricModalHostViewController: …> is not supported, and may result in incorrect safe area insets and a corrupt root presentation. Make sure <RCTFabricModalHostViewController: …> is in the view controller hierarchy before presenting from it. Will become a hard exception in a future release.

Affected Platforms

  • iOS
  • Android
  • Web
  • Other

Library Version

3.10.0

Environment Info

System:
  OS: macOS 26.4.1
  CPU: (16) arm64 Apple M3 Max
  Memory: 2.03 GB / 64.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 24.12.0
    path: /Users/joel.kanzelmeyer/.nvm/versions/node/v24.12.0/bin/node
  Yarn:
    version: 4.12.0
    path: /Users/joel.kanzelmeyer/.nvm/versions/node/v24.12.0/bin/yarn
  npm:
    version: 11.6.2
    path: /Users/joel.kanzelmeyer/.nvm/versions/node/v24.12.0/bin/npm
  Watchman:
    version: 2024.10.14.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 25.2
      - iOS 26.2
      - macOS 26.2
      - tvOS 26.2
      - visionOS 26.2
      - watchOS 26.2
  Android SDK: Not Found
IDEs:
  Android Studio: 2025.3 AI-253.31033.145.2533.15113396
  Xcode:
    version: 26.2/17C52
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.11
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 20.1.3
    wanted: ^20.1.3
  react:
    installed: 19.1.0
    wanted: 19.1.0
  react-native:
    installed: 0.81.5
    wanted: 0.81.5
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Steps to Reproduce

The bug is triggered whenever TrueSheet's presenter is a UIViewController that cannot be walked back to the window's root VC via parentpresenting. Two common shapes that produce it:

  1. RN <Modal> inside a custom React Navigation navigator / pager: the <Modal>'s presenter ([self reactViewController] in Fabric's RCTModalHostViewComponentView) is a VC attached to the view tree via addSubview: rather than addChildViewController: — detached from UIKit's containment. A TrueSheet rendered inside that Modal inherits the detachment.

  2. Any custom native/JS navigator that parks its screens' VCs in the view hierarchy via addSubview: rather than proper VC containment.

Minimal JS repro shape (inside the non-trivial case):

// inside a react-navigation screen (or similar), under New Arch
<Modal transparent visible>
  <View style={{ flex: 1 }}>
    <TrueSheet ref={ref} detents={[0.5]} dimmed>
      <Text>Hello</Text>
    </TrueSheet>
    <Button title="open" onPress={() => ref.current?.present()} />
  </View>
</Modal>

Observed vs expected

  Observed Expected
Sheet content ✓ renders above everything
Dim layer Appears in the key window behind the outer Modal's content Covers the content directly below the sheet
Console UIKit "detached view controller" warning No warning

Repro

https://github.com/kanzelm3/truesheet-detached-vc-repro

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrepro providedGood! Repro is provided

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions