Repository navigation
showDragHandle is not visible when a CupertinoSheetRoute covers another CupertinoSheetRoute #187697
Copy link
Copy link
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listhas reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: cupertino_uicupertino_ui package in flutter/packagescupertino_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.team-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages team
Description
Steps to reproduce
- Push a
CupertinoSheetRoute(sheet A) withshowDragHandle: true— note its handle renders correctly. - From within sheet A's content, push a second
CupertinoSheetRoute(sheet B) withshowDragHandle: trueas well (soCupertinoSheetRoute.hasParentSheet(context)istruefor sheet B). - Wait for sheet B to fully settle into view and inspect its top edge.
Expected results
Sheet B shows a drag handle identical to sheet A's, since both are constructed identically with showDragHandle: true through the same _sheetWithDragHandle code path.
Actual results
Sheet A (the bottom/covered sheet) shows its handle correctly. Sheet B (the topmost/covering sheet) shows no handle at all — its content begins flush with the top edge of the sheet, even though showDragHandle: true is set identically on both routes.
Investigation notes:
- Both sheets' content widgets use an identical shell (
ClipRRect→Material→SafeArea(top: false)), ruling out content-specific causes. _sheetWithDragHandle(https://github.com/flutter/flutter/blob/559ffa3f75/packages/flutter/lib/src/cupertino/sheet.dart#L699-L736) builds an identicalStack(content first, handle painted on top) regardless ofhasParentSheet— so the handle-painting code itself isn't gated on nesting.- However,
CupertinoSheetRoute.hasParentSheet(context)does change behavior elsewhere whentrue: a different slide-in offset tween is used (_kBottomUpTweenWhenCoveringOtherSheet, https://github.com/flutter/flutter/blob/559ffa3f75/packages/flutter/lib/src/cupertino/sheet.dart#L511-L513) and a delegated secondary transition is applied to the covered sheet underneath (https://github.com/flutter/flutter/blob/559ffa3f75/packages/flutter/lib/src/cupertino/sheet.dart#L314-L316). This suggests the "covering sheet" geometry/positioning differs in a way that clips or repositions the new sheet's top edge — including its handle — out of the visible region.
Code sample
Code sample
import 'package:flutter/cupertino.dart';
void main() => runApp(const CupertinoApp(home: _Demo()));
class _Demo extends StatelessWidget {
const _Demo();
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Center(
child: CupertinoButton.filled(
child: const Text('Open Sheet A'),
onPressed: () => Navigator.of(context, rootNavigator: true).push(
CupertinoSheetRoute<void>(
showDragHandle: true, // shows correctly
scrollableBuilder: (ctx, sc) => _SheetContent(
scrollController: sc,
title: 'Sheet A (handle visible)',
onOpenNested: () => Navigator.of(ctx, rootNavigator: true).push(
CupertinoSheetRoute<void>(
showDragHandle: true, // NOT shown — this is the bug
scrollableBuilder: (ctx2, sc2) => _SheetContent(
scrollController: sc2,
title: 'Sheet B (handle missing)',
onOpenNested: null,
),
),
),
),
),
),
),
),
);
}
}
class _SheetContent extends StatelessWidget {
const _SheetContent({
required this.scrollController,
required this.title,
required this.onOpenNested,
});
final ScrollController scrollController;
final String title;
final VoidCallback? onOpenNested;
@override
Widget build(BuildContext context) {
return ListView(
controller: scrollController,
padding: const EdgeInsets.all(20),
children: [
Text(title, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
if (onOpenNested != null)
CupertinoButton.filled(onPressed: onOpenNested, child: const Text('Open Sheet B')),
],
);
}
}
### Screenshots or Video
<img width="568" height="1084" alt="Image" src="https://github.com/user-attachments/assets/2e5dcd07-e957-4474-97a2-400cf2ec4d96" />
<img width="568" height="1084" alt="Image" src="https://github.com/user-attachments/assets/725e6128-486f-4e30-9c26-ad11fcc0a425" />
<details open>
<summary>Screenshots / Video demonstration</summary>
[Upload media here]
</details>
### Logs
<details open><summary>Logs</summary>
```console
[Paste your logs here]Flutter Doctor output
Doctor output
theo@Theos-MacBook-Pro xyz % flutter doctor -v
[✓] Flutter (Channel stable, 3.44.0, on macOS 26.5.1 25F80 darwin-arm64, locale en-US) [496ms]
• Flutter version 3.44.0 on channel stable at /Users/theo/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 559ffa3f75 (3 weeks ago), 2026-05-15 14:13:13 -0700
• Engine revision 4c525dac5e
• Dart version 3.12.0
• DevTools version 2.57.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging,
enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [3.6s]
• Android SDK at /Users/theo/Library/Android/sdk
• Emulator version 36.5.11.0 (build_id 15261927) (CL:N/A)
• Platform android-36, build-tools 36.0.0
• ANDROID_HOME = /Users/theo/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.10+-117844308-b1163.108)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.4.1) [1,064ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17E202
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [4ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (3 available) [7.1s]
• iPhone 17 Pro (mobile) • C86719DB-BF57-4694-AA94-61AA93AC2CB5 • ios • com.apple.CoreSimulator.SimRuntime.iOS-26-4 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 26.5.1 25F80 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 148.0.7778.217
[✓] Network resources [1,017ms]
• All expected network resources are available.
• No issues found!
theo@Theos-MacBook-Pro xyz % Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listhas reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: cupertino_uicupertino_ui package in flutter/packagescupertino_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.team-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages team
Activity
suryaKommana2662 commentedon Jun 9, 2026
@art-sparrow Thank you for the report and detailed reproduction steps. I was able to reproduce the reported behavior where a nested
CupertinoSheetRoutedoes not display its drag handle whenshowDragHandle: trueis enabled. This appears related to #187057 as both reports involve nestedCupertinoSheetRoutes. However, the reported symptoms are different, so I am keeping this issue separate for now and routing it to theteam-designfor further investigation.theprantadutta commentedon Sep 25, 2026
I was going to take this (I just ported the related #187693 fix to
cupertino_uiin flutter/packages#13011), but I can't reproduce it on currentcupertino_uimain, so I wanted to check before writing a fix.I rebuilt the sample from the report as a widget test —
scrollableBuilder, both sheets pushed on the root navigator, and a scrollingListViewunder an opaque background — then screenshotted the settled state after opening sheet B. Sheet B's handle renders in every configuration I tried:sheet.dartfrom just before [cupertino_ui] Fix covered sheet revealing root route through top gap packages#12530 ("Fix covered sheet revealing root route through top gap"), in case that change fixed it as a side effectIn all four, B's handle sits 5px below B's top edge, as
_sheetWithDragHandleintends. After #12530, sheet A's handle also shows just above it, peeking out behind B.@art-sparrow, is there anything in your setup that my test wouldn't cover? For example: a physical device versus the simulator, dark mode, a specific iOS version, or content that isn't in the minimal sample. If it still happens for you on 3.47 / current
cupertino_ui, a screenshot would help a lot and I'm happy to dig further.art-sparrow commentedon Sep 25, 2026
Hi @theprantadutta. I upgraded to Flutter 3.47 and will double back if the issue recurs.