Skip to content

[iOS] A sheet's content resizing just after it presents over another sheet hides the sheet under it when it's dismissed soon after #1000

Open

Description

@philiplindberg

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

When a sheet is presented over another sheet that stays presented, and its content changes size just after it presents, dismissing it within about half a second leaves the sheet underneath missing for several frames once the top sheet is down. The sheet underneath then pops back.

Affected Platforms

  • iOS
  • Android
  • Web
  • Other

Library Version

4.0.1

Environment Info

info Fetching system and libraries information...
System:
  OS: macOS 27.0.1
  CPU: (10) arm64 Apple M1 Pro
  Memory: 174.22 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 26.4.0
    path: /opt/homebrew/bin/node
  Yarn:
    version: 1.22.22
    path: /opt/homebrew/bin/yarn
  npm:
    version: 11.17.0
    path: /opt/homebrew/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.17.0
    path: /opt/homebrew/lib/ruby/gems/4.0.0/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 27.0
      - iOS 27.1
      - macOS 27.0
      - tvOS 27.0
      - visionOS 27.0
      - watchOS 27.0
  Android SDK:
    API Levels:
      - "28"
      - "29"
      - "30"
      - "31"
      - "32"
      - "33"
      - "34"
      - "35"
      - "36"
      - "37"
    Build Tools:
      - 28.0.3
      - 29.0.2
      - 30.0.2
      - 30.0.3
      - 31.0.0
      - 32.0.0
      - 33.0.0
      - 33.0.1
      - 34.0.0
      - 35.0.0
      - 36.0.0
      - 37.0.0
    System Images:
      - android-29 | Intel x86 Atom
      - android-29 | Intel x86 Atom_64
      - android-30 | Intel x86_64 Atom
      - android-30 | Google APIs ARM 64 v8a
      - android-31 | ARM 64 v8a
      - android-32 | Google APIs ARM 64 v8a
      - android-32 | Google Play ARM 64 v8a
      - android-32 | Google Play Intel x86 Atom_64
      - android-33 | Google APIs ARM 64 v8a
      - android-35 | Google Play ARM 64 v8a
      - android-36 | Google Play ARM 64 v8a
      - android-37.2-beta3 | 16 KB Page Size Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2026.1 AI-261.26222.65.2613.16025427
  Xcode:
    version: 27.1/27A9275
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.1
    path: /usr/bin/javac
  Ruby:
    version: 4.0.5
    path: /opt/homebrew/opt/ruby/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 19.3.0
    wanted: 19.3.0
  react-native:
    installed: 0.88.1
    wanted: 0.88.1
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Steps to Reproduce

  1. In the repro, open the screen "Stacked sheets". The parent sheet has detents={['auto', 1]}, dismissible={false} and dimmed={false}. The child has detents={[1]} and adds a 40 pt view to its content in onDidPresent.
  2. Turn on "Child content grows once presented".
  3. Tap "Cycle 10 times". It presents the child and dismisses it 250 ms after onDidPresent, ten times.

Expected: the parent sheet is there as soon as the child slides off it.
Actual: once the child is down, the parent is missing for several frames each time, then reappears all at once. With the switch off, it's there the moment the child uncovers it.

Repro

https://github.com/philiplindberg/true-sheet-repros

Additional Context

Expo SDK 58, React Native 0.88, new architecture, 4.0.1 with no patches. In a screen recording of the iPhone 18 Pro simulator (iOS 27), the parent's button stayed hidden 1.02–1.04 s per cycle with the switch on and 0.96–0.97 s with it off, over ten cycles each. In our app on an iPhone 18 Pro (iOS 27), a form sheet whose content settles just after it presents did this on 8 of 10 swipe dismissals.

What happens: when the child fully covers the parent, UIKit hides the parent (alpha 0 on its UIDropShadowView) in a layout of the presentation stack, and shows it again (alpha 1, not animated) when a dismissal starts. Normally the hide is instant. Here the child's content grows after it presents, so setupSheetDetentsForSizeChange runs on the child, which has no 'auto' or 'peek' detent, and calls invalidateDetentsAnimated. The first layout of the stack after the present then runs inside animateChanges, so UIKit's hide becomes an animation of about 0.5 s. If the dismissal starts before it ends, the unanimated alpha 1 changes only the model value, and the hide animation goes on drawing the parent at opacity 0 until it finishes.

A fix: in setupSheetDetentsForSizeChange, invalidate only when the sheet has an 'auto' or 'peek' detent, the only ones that resolve from those heights:

if (![self.detents containsObject:@(-1)] && ![self.detents containsObject:@(-2)]) {
  return;
}

With that, in our app the hide is instant again and the parent no longer goes missing (0 of 9 dismissals on 4.0.0, 0 of 8 on 4.0.1). It doesn't cover a sheet with an 'auto' or 'peek' detent that resizes just after presenting over another sheet, since that one still invalidates animated; a fuller fix might keep the stack's layout out of animateChanges. Happy to open a PR for either.

Activity

  1. github-actions commented on Oct 30, 2026

    @github-actions

    Hey @philiplindberg! Thanks for opening the issue.

    It looks like your issue is missing a valid reproduction link.

    A minimal reproduction helps us investigate and fix the issue faster. Without one, we may not be able to help.

    Please provide one of the following:

    • A GitHub repository under your username
    • An Expo Snack

    See "How to create a Minimal, Reproducible Example" for more guidance.

    You can edit your original issue or leave a comment with the repro link. Issues without reproductions may be closed after 14 days.

  2. added
    needs reproNeed to replicate this issue
    and removed
    needs reproNeed to replicate this issue
    on Oct 30, 2026
  3. github-actions commented on Oct 30, 2026

    @github-actions

    Thank you for providing a repro! We'll take a look at this issue soon.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions