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

ParameterTypeDefaultDescription
openBooleanControls whether the bottom sheet is visible.
onDismissRequest() -> UnitCalled when the user swipes down or taps the scrim.
modifierModifierModifierApplied to the inner content Column.
sheetStateSheetStaterememberModalBottomSheetState()Controls the sheet's animation state. Use with a coroutine scope to animate hide before clearing open.
title@Composable () -> UnitTitle slot. Wrap content in DrawerTitle.
description@Composable () -> UnitDescription slot. Wrap content in DrawerDescription.
content@Composable ColumnScope.() -> UnitMain content slot between the header and footer.
footer(@Composable RowScope.() -> Unit)?nullOptional footer slot. Rendered in a right-aligned Row. Typically contains DrawerCancel and DrawerAction.
showCloseButtonBooleanfalseWhen true, renders an × icon button in the header row.
shouldDismissOnBackPressBooleantrueWhen 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.

ParameterTypeDefaultDescription
modifierModifierModifierApplied to the title container.
content@Composable () -> UnitSlot 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.

ParameterTypeDefaultDescription
modifierModifierModifierApplied to the description container.
content@Composable () -> UnitSlot content — typically a Text.

DrawerAction

A primary action button using ButtonVariant.Default. Place inside the footer slot.

ParameterTypeDefaultDescription
onClick() -> UnitCalled when the button is tapped.
modifierModifierModifierApplied to the button.
content@Composable () -> UnitButton label — typically a Text.

DrawerCancel

A secondary cancel button using ButtonVariant.Outline. Place inside the footer slot.

ParameterTypeDefaultDescription
onClick() -> UnitCalled when the button is tapped.
modifierModifierModifierApplied to the button.
content@Composable () -> UnitButton label — typically a Text.

Animating the sheet closed — calling showDrawer = false directly snaps the sheet away without animation. For a smooth slide-out, use scope.launch { sheetState.hide() }.invokeOnCompletion { if (!sheetState.isVisible) showDrawer = false }.

Edit this page on GitHub