Drawer
Displays a bottom sheet.
Drawer wraps Material3's ModalBottomSheet with a themed drag handle, header row, scrollable content slot, and an optional right-aligned footer. Unlike Dialog, the title, description, and content slots are required; only footer is optional.
Usage
With Close Button
Set showCloseButton = true to render an × icon button in the top-right corner of the header row, in addition to the drag-handle dismiss.
import com.komoui.components.Button
import com.komoui.components.Drawer
import com.komoui.components.DrawerDescription
import com.komoui.components.DrawerTitle
@Composable
fun Example() {
var showDrawer by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(onClick = { showDrawer = true }) {
Text("Open Drawer")
}
}
Drawer(
open = showDrawer,
onDismissRequest = { showDrawer = false },
showCloseButton = true,
title = { DrawerTitle { Text("Notifications") } },
description = { DrawerDescription { Text("Manage your notification preferences.") } },
content = {
Text(
text = "No notifications yet.",
color = MaterialTheme.styles.mutedForeground
)
}
)
}Prevent Back-Press Dismiss
Set shouldDismissOnBackPress = false to require the user to explicitly tap a footer button to close the sheet.
import com.komoui.components.Button
import com.komoui.components.Drawer
import com.komoui.components.DrawerAction
import com.komoui.components.DrawerDescription
import com.komoui.components.DrawerTitle
@Composable
fun Example() {
var showDrawer by remember { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
fun hideDrawer() {
scope.launch { sheetState.hide() }.invokeOnCompletion {
if (!sheetState.isVisible) showDrawer = false
}
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(onClick = { showDrawer = true }) {
Text("Open Drawer")
}
}
Drawer(
open = showDrawer,
onDismissRequest = { showDrawer = false },
sheetState = sheetState,
shouldDismissOnBackPress = false,
title = { DrawerTitle { Text("Terms of Service") } },
description = { DrawerDescription { Text("Please read and accept to continue.") } },
content = {
Text(
text = "By using this app you agree to our terms...",
color = MaterialTheme.styles.mutedForeground
)
},
footer = {
DrawerAction(onClick = ::hideDrawer) {
Text("I Accept")
}
}
)
}API Reference
Drawer
| Parameter | Type | Default | Description |
|---|---|---|---|
open | Boolean | — | Controls whether the bottom sheet is visible. |
onDismissRequest | () -> Unit | — | Called when the user swipes down or taps the scrim. |
modifier | Modifier | Modifier | Applied to the inner content Column. |
sheetState | SheetState | rememberModalBottomSheetState() | Controls the sheet's animation state. Use with a coroutine scope to animate hide before clearing open. |
title | @Composable () -> Unit | — | Title slot. Wrap content in DrawerTitle. |
description | @Composable () -> Unit | — | Description slot. Wrap content in DrawerDescription. |
content | @Composable ColumnScope.() -> Unit | — | Main content slot between the header and footer. |
footer | (@Composable RowScope.() -> Unit)? | null | Optional footer slot. Rendered in a right-aligned Row. Typically contains DrawerCancel and DrawerAction. |
showCloseButton | Boolean | false | When true, renders an × icon button in the header row. |
shouldDismissOnBackPress | Boolean | true | When false, the back-press gesture will not dismiss the sheet. |
DrawerTitle
Slot wrapper rendered inside the title parameter. Typography (18 sp, SemiBold, foreground color) is applied by the parent Drawer via ProvideTextStyle.
| Parameter | Type | Default | Description |
|---|---|---|---|
modifier | Modifier | Modifier | Applied to the title container. |
content | @Composable () -> Unit | — | Slot content — typically a Text. |
DrawerDescription
Slot wrapper rendered inside the description parameter. Typography (14 sp, mutedForeground color) is applied by the parent Drawer via ProvideTextStyle.
| Parameter | Type | Default | Description |
|---|---|---|---|
modifier | Modifier | Modifier | Applied to the description container. |
content | @Composable () -> Unit | — | Slot content — typically a Text. |
DrawerAction
A primary action button using ButtonVariant.Default. Place inside the footer slot.
| Parameter | Type | Default | Description |
|---|---|---|---|
onClick | () -> Unit | — | Called when the button is tapped. |
modifier | Modifier | Modifier | Applied to the button. |
content | @Composable () -> Unit | — | Button label — typically a Text. |
DrawerCancel
A secondary cancel button using ButtonVariant.Outline. Place inside the footer slot.
| Parameter | Type | Default | Description |
|---|---|---|---|
onClick | () -> Unit | — | Called when the button is tapped. |
modifier | Modifier | Modifier | Applied to the button. |
content | @Composable () -> Unit | — | Button label — typically a Text. |
Edit this page on GitHubAnimating the sheet closed — calling
showDrawer = falsedirectly snaps the sheet away without animation. For a smooth slide-out, usescope.launch { sheetState.hide() }.invokeOnCompletion { if (!sheetState.isVisible) showDrawer = false }.