Repository navigation
Conversation
A <bottom-sheet> was a bare panel: no title, no close button, its content starting at the top edge under the grabber. Apps drew their own title row and X in every sheet and guessed the gap under the handle. `title` (fluent `title()`) now draws the sheet the way the platform's own sheets look. On iOS the content goes in a NavigationStack whose inline bar carries the title and the system's close button on its leading edge, as Apple's HIG places a sheet's Cancel/Close: `Button(role: .close)` on iOS 26, the filled xmark circle before it. Close sets `isPresented` to false, so onDismiss reports it as `@dismiss`, as it does a swipe-down. A permanent sheet gets no close button. A fit sheet adds the bar's measured height to its content's. Material's modal bottom sheet has no top bar or close button, it closes on a swipe down, a tap on the scrim or back. So on Android the title is titleLarge heading text under the drag handle, at a 20dp inset. `close-label` (fluent `closeLabel()`) sets the close button's VoiceOver label, since the package can't translate it. Unset, the system's own label stays. Untitled sheets are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Would be great to see screenshots of before and after, dark and light of this for both platforms |
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.
A
<bottom-sheet>is a bare panel. It has no title and no close button, and its content starts at the top edge, under the grabber. So an app that wants a titled sheet draws its own title row and X inside it and guesses the gap under the handle. The result looks almost like a system sheet, but not quite, and the app has to work out the iOS and Android differences itself.This adds a
titleattribute and a fluenttitle(). A titled sheet looks like the platform's own sheets:NavigationStackwith an inline.navigationTitle. The system's close button is at.cancellationAction:Button(role: .close)on iOS 26, the filled xmark circle before it. Apermanentsheet gets no close button.titleLargeheading text under the drag handle, at a 20dp inset, in the theme'son-surfacecolor and default font.Untitled sheets don't change.
We built this in our app first, as a local patch on 0.9.0, and moved our sheets to it. This PR is that patch, so we can delete it.
Try it
Tap Open. On iOS, "Filters" is in the sheet's bar with a close button on the left. Tapping it logs
closeSheet(), as a swipe-down does. On Android, "Filters" sits under the drag handle.How
Element.
titleandclose-label(orcloseLabel) become thetitleandclose_labelprops.close-labelis the close button's VoiceOver label. The package can't translate it, so an app whose language can differ from the system's passes its own. Unset, iOS 26 keeps the system's label and the older button reads "Close".iOS. A
SheetTitleBarmodifier puts a titled sheet's content in theNavigationStack. An untitled sheet's content is returned as it is. The close button setsisPresentedto false, soonDismisssends@dismiss, the same as for a swipe-down. That still holds with #196, which only skips the closes PHP starts throughvisible.A fit sheet also measures the bar and adds its height to the content's, so the fit detent holds both. The bar's height is the top safe-area inset of a background that reaches up under the bar.
Android. A
SheetHeadingcomposable comes first in the sheet's column when the title isn't empty.Docs. The element's docblock and the
bottom-sheetrow of the Boost skill.Testing
tests/BottomSheetRendererTest.phpgets four tests that pin the Swift and the Kotlin, andtests/CollectorElementsTest.phpgets three for the element's props. All of them fail without the change, except the one that checks an untitled sheet sends notitle.composer test(492 passed) andcomposer lint:testpass.onDismiss.tests/androidRobolectric module locally, with stubs forsendSheetDismissEventandRenderNode. A titled fit sheet draws its title above its content, and an untitled one draws none. I left that test out of this PR, because the module doesn't build the sheet renderer today. Happy to add it if you'd like it.This branch, #196 and #200 (the grabber) all edit the same renderer and test file. Any two of them, or all three, merge cleanly in either order, and the suite passes on the merged tree.
🤖 Generated with Claude Code