Sheet is a UI component that appears at the bottom of the screen over the main content and provides additional actions or information. Bottom Sheet is the most common type, defined in the guidelines of Material Design 3 (Google, 2024). Unlike dialog windows, a Sheet does not fully block interaction with the background and supports collapsed and expanded states. Understanding the types and behavior of Sheets is essential for building convenient navigation in mobile applications.
Key Takeaways
Sheet is a surface-level UI component that slides up from the bottom of the screen and displays additional content or actions without taking the user away from the current screen. Unlike full-screen transitions, a Sheet preserves context: the user can see the background screen and understands where the Sheet came from.
The architecture of a Sheet is based on a container with adjustable height. In its minimal state (collapsed), only part of the content is visible — usually a title or a small panel. The user can drag the Sheet up to expand it (expanded) or swipe it down to close it. This behavior resembles a physical sheet of paper being pulled out from under a stack — hence the name.
Google in the Material Design 3 guidelines (2024) highlights two key scenarios for using Sheets: displaying additional actions that did not fit on the main toolbar, and showing forms or detailed information without navigating to a separate screen. On iOS, Apple added system-level Sheet support starting with iOS 15 via UISheetPresentationController, confirming the universality of the pattern.
Material Design defines three types of Bottom Sheet, each with its own behavior and use case. Choosing the right type directly affects the user experience and compliance with platform guidelines.
Standard Bottom Sheet is a non-modal component: the user can interact with the background screen without closing the Sheet. For example, while browsing a product list in the background, the user sees filters in a Bottom Sheet and can change them without closing the panel. The Sheet adjusts its height to the content — from 30% to 90% of the screen.
The standard Bottom Sheet does not block the background and allows interaction with the main content. This is a key difference from a modal Sheet, which requires a mandatory action to proceed. Use a standard Sheet when the additional information is not critical to the main scenario.
Modal Bottom Sheet blocks interaction with the background screen until the user performs an action inside the Sheet. Such a Sheet is always shown in the expanded state and requires explicit dismissal — via a button, action, or swipe down. Material Design recommends a modal Sheet for login forms, confirmations, and critical settings.
On Android, the modal Bottom Sheet is implemented via BottomSheetDialogFragment, which automatically blocks the background. On iOS, similar behavior is provided by the modal variant of UISheetPresentationController with the .mediumDetent parameter. A modal Sheet should only be used when the context requires the user's attention.
Expanding Bottom Sheet combines the properties of standard and modal: it starts as non-modal in the collapsed state but becomes modal when dragged up. In practice, this means the user can first glance at the content and then decide — expand the Sheet for detailed study or close it.
This pattern is especially popular in maps and navigation apps, where the bottom panel shows brief information about a route point, and when swiped up, it expands with details. Google Maps uses this exact expanding Sheet to display information about places and routes.
| Sheet Type | Background Blocking | Initial State | Example |
|---|---|---|---|
| Standard | No | Collapsed | Filters in catalog |
| Modal | Yes | Expanded | Login form |
| Expanding | Partial | Collapsed | Place card |
Android SDK provides several APIs for implementing Bottom Sheet, ranging from the classic View-based approach to modern Jetpack Compose. The Material Components Library for Android includes ready-made implementations of BottomSheetDialogFragment and BottomSheetBehavior.
BottomSheetBehavior is a class from Material Components that attaches to any View and controls its position on the screen. The developer sets three states: STATE_COLLAPSED, STATE_EXPANDED, and STATE_HIDDEN. Behavior automatically handles drag gestures and animation.
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200
Jetpack Compose provides a more declarative API through the ModalBottomSheet component from Material 3. Unlike the View-based approach, in Compose the Bottom Sheet is a composable function that accepts state and content. The Sheet automatically animates appearance, dismissal, and height changes when dragged.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Text("Filters")
Button(onClick = onDismiss) { Text("Apply") }
}
}
BottomSheetDialogFragment is a specialized DialogFragment that displays as a Bottom Sheet. It automatically handles modality, lifecycle, and configuration changes. The developer only needs to override onCreateView and return the Sheet layout. According to Google documentation (Android Developers, 2024), BottomSheetDialogFragment is the recommended approach for modal Bottom Sheets in classic Android.
Apple introduced system-level Sheet support starting with iOS 15 via UISheetPresentationController. Before that, developers implemented Bottom Sheet manually through custom transitions or third-party libraries. Apple's native Sheet supports detents — predefined expansion levels.
UISheetPresentationController is a built-in presentation controller that displays a View Controller as a Sheet. The developer specifies an array of detents — height values at which the Sheet can stop. iOS 16 added custom detents with arbitrary height. Apple recommends using medium (.medium) and large (.large) detents as the primary ones.
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium, .large]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)
SwiftUI provides the .sheet modifier, which binds the Sheet display to state. When a published variable becomes true, SwiftUI automatically shows the Sheet. SwiftUI also supports detents via the .presentationDetents modifier, added in iOS 16.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Show Sheet") { showSheet = true }
.sheet(isPresented: $showSheet) {
FilterView()
.presentationDetents([.medium, .large])
}
}
}
Cross-platform frameworks also support Bottom Sheet, adapting the behavior to the target platform. Flutter and React Native provide built-in and custom implementations with varying degrees of flexibility.
Flutter SDK contains two methods for displaying Bottom Sheet: showBottomSheet (standard) and showModalBottomSheet (modal). Material Design in Flutter follows the same principles as in Android — the Sheet appears from the bottom, supports dragging, and has adjustable height. For expanded behavior with detents, DraggableScrollableSheet is used.
Scaffold.of(context).showBottomSheet((context) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("Sheet Content"),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text("Close")
)
]
)
);
})
React Native does not have a built-in Bottom Sheet component in its core, so developers use third-party libraries. The most popular one is @gorhom/bottom-sheet (over 7 thousand stars on GitHub, 2024). It provides a gesture-driven Bottom Sheet with support for snap points, animations, and sticky headers. The library is built on Reanimated 2 and Gesture Handler for 60 FPS performance.
Proper use of Bottom Sheet requires adherence to platform guidelines and understanding of scenarios where a Sheet is appropriate. Let us review key recommendations and common mistakes when designing Sheets.
Bottom Sheet is optimal for actions that are supplementary to the main content on the screen. Filters, sorting, option selection, brief item information — typical scenarios. Material Design recommends using Bottom Sheet for tools that should not take up the entire screen but require more space than an Action Sheet or Popup Menu.
Do not use Bottom Sheet for critical warnings or errors — dialog windows are more suitable for this. Avoid Sheets with a large number of input fields that require scrolling: the user struggles to reach the keyboard and loses context. If a Sheet contains more than seven action items, consider a separate screen instead of a Sheet.
A common mistake is setting peekHeight (height in the collapsed state) to more than 40% of the screen. The user cannot tell whether they are seeing the Sheet fully or if it can be expanded. Material Design recommends peekHeight within 15-30% of the screen height to leave a noticeable portion of content hidden and motivate dragging.
On iOS, users expect that a Sheet can be closed by swiping down from any position. If you disable this gesture (via UISheetPresentationController.prefersEdgeAttachedInCompactHeight), the user experiences frustration trying to close the Sheet in the familiar way. Apple Human Interface Guidelines (2024) emphasize that swipe-to-dismiss is a basic user expectation on iOS.
Frequently Asked Questions
Bottom Sheet does not fully block the background and supports dragging, while a dialog window is modal and requires a mandatory action. Bottom Sheet is better suited for supplementary options, while a dialog is for critical confirmations.
Yes, but it requires setting adjustResize or adjustPan in the Android manifest. On iOS, the keyboard automatically lifts the Sheet. Flutter and React Native require manual handling via MediaQuery for correct positioning.
It is recommended to have no more than 5-7 items in a standard Sheet. If there is more content, use scrolling or category breakdown. Material Design advises not to exceed 90% of the screen height in the expanded state.
For a modal Sheet, set setCancelable(true) on Android or isModalInPresentation = false on iOS. In Jetpack Compose, onDismissRequest automatically handles background tap. In SwiftUI, swipe down is the default behavior.
Yes, all native implementations support VoiceOver and TalkBack. Ensure that FocusManager correctly moves focus to the Sheet when it opens and returns it when it closes. Custom implementations require manual accessibility configuration.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also