Bottom sheets

If you want to implement a bottom sheet, you can use the ModalBottomSheet composable.

You can use the content slot, which uses a ColumnScope to layout sheet content composables in a column:

ModalBottomSheet(onDismissRequest = { /* Executed when the sheet is dismissed */ }) {
    // Sheet content
}

Programmatically expanding and collapsing the sheet is done using SheetState. You can use rememberSheetState to create an instance of SheetState that should be passed to ModalBottomSheet with the sheetState parameter. SheetState provides access to the show and hide functions, as well as properties related to the current sheet state. These suspending functions require a CoroutineScope — for example, using rememberCoroutineScope — and can be called in response to UI events. Make sure to remove the ModalBottomSheet from composition upon hiding the bottom sheet.

val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
var showBottomSheet by remember { mutableStateOf(false) }
Scaffold(
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show bottom sheet") },
            icon = { Icon(Icons.Filled.Add, contentDescription = "") },
            onClick = {
                showBottomSheet = true
            }
        )
    }
) { contentPadding ->
    // Screen content

    if (showBottomSheet) {
        ModalBottomSheet(
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Button(onClick = {
                scope.launch { sheetState.hide() }.invokeOnCompletion {
                    if (!sheetState.isVisible) {
                        showBottomSheet = false
                    }
                }
            }) {
                Text("Hide bottom sheet")
            }
        }
    }
}