Skip to content

SuperBottomSheet

SuperBottomSheet is a bottom sheet component in Miuix that slides up from the bottom of the screen. Supports swipe-to-dismiss gestures and custom styling.

Prerequisite

This component depends on Scaffold providing MiuixPopupHost to render popup content. It must be used within Scaffold, otherwise popup content will not render correctly.

Import

kotlin
import top.yukonga.miuix.kmp.extra.SuperBottomSheet
import top.yukonga.miuix.kmp.theme.LocalDismissState

Basic Usage

SuperBottomSheet component provides basic bottom sheet functionality:

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Bottom Sheet",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Bottom Sheet Title",
        onDismissRequest = { showBottomSheet = false }
    ) {
        Text(text = "This is the content of the bottom sheet")
    }
}

Properties

SuperBottomSheet Properties

Property NameTypeDescriptionDefault ValueRequired
showBooleanWhether to show the bottom sheet-Yes
modifierModifierModifier applied to the bottom sheetModifierNo
titleString?Bottom sheet titlenullNo
startAction@Composable (() -> Unit)?Optional composable for start action (e.g., close button)nullNo
endAction@Composable (() -> Unit)?Optional composable for end action (e.g., submit button)nullNo
backgroundColorColorBottom sheet background colorBottomSheetDefaults.backgroundColor()No
enableWindowDimBooleanWhether to enable dimming layertrueNo
cornerRadiusDpCorner radius of the top cornersBottomSheetDefaults.cornerRadiusNo
sheetMaxWidthDpMaximum width of the bottom sheetBottomSheetDefaults.maxWidthNo
onDismissRequest(() -> Unit)?Called when the user requests dismissal (outside tap or back)nullNo
onDismissFinished(() -> Unit)?Callback after bottom sheet fully dismissesnullNo
outsideMarginDpSizeBottom sheet external marginBottomSheetDefaults.outsideMarginNo
insideMarginDpSizeBottom sheet internal content marginBottomSheetDefaults.insideMarginNo
defaultWindowInsetsPaddingBooleanWhether to apply default window insets paddingtrueNo
dragHandleColorColorDrag indicator colorBottomSheetDefaults.dragHandleColor()No
allowDismissBooleanWhether to allow dismissing the sheet via drag or back gesturetrueNo
enableNestedScrollBooleanWhether to enable nested scrolling for the contenttrueNo
renderInRootScaffoldBooleanWhether to render the bottom sheet in the root (outermost) Scaffold. When true, it covers the full screen. When false, it renders within the current Scaffold's boundstrueNo
content@Composable () -> UnitBottom sheet content-Yes

BottomSheetDefaults Object

The BottomSheetDefaults object provides default settings for the SuperBottomSheet component.

BottomSheetDefaults Properties

Property NameTypeDescription
cornerRadiusDpDefault corner radius (28.dp)
maxWidthDpDefault maximum width (640.dp)
outsideMarginDpSizeDefault bottom sheet external margin
insideMarginDpSizeDefault bottom sheet internal margin

BottomSheetDefaults Functions

Function NameReturn TypeDescription
backgroundColor()ColorGet default background color
dragHandleColor()ColorGet default drag indicator color

Advanced Usage

Custom Styled Bottom Sheet

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Custom Styled Bottom Sheet",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Custom Style",
        backgroundColor = MiuixTheme.colorScheme.surfaceVariant,
        dragHandleColor = MiuixTheme.colorScheme.primary,
        outsideMargin = DpSize(16.dp, 0.dp),
        insideMargin = DpSize(32.dp, 16.dp),
        onDismissRequest = { showBottomSheet = false }
    ) {
        Column {
            Text("Custom styled bottom sheet")
            Spacer(modifier = Modifier.height(16.dp))
            TextButton(
                text = "Close",
                onClick = { showBottomSheet = false },
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

Bottom Sheet with List Content

kotlin
var showBottomSheet by remember { mutableStateOf(false) }
var selectedItem by remember { mutableStateOf("") }

Scaffold {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        TextButton(
            text = "Show Selection List",
            onClick = { showBottomSheet = true }
        )
        
        Text("Selected: $selectedItem")
    }

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Select Item",
        onDismissRequest = { showBottomSheet = false }
    ) {
        LazyColumn {
            items(20) { index ->
                Text(
                    text = "Item ${index + 1}",
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable {
                            selectedItem = "Item ${index + 1}"
                            showBottomSheet = false
                        }
                        .padding(vertical = 12.dp)
                )
            }
        }
    }
}

Without Dimming Layer

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Bottom Sheet Without Dim",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "No Dimming",
        enableWindowDim = false,
        onDismissRequest = { showBottomSheet = false }
    ) {
        Text("This bottom sheet has no background dimming layer")
        Spacer(modifier = Modifier.height(16.dp))
        TextButton(
            text = "Close",
            onClick = { showBottomSheet = false },
            modifier = Modifier.fillMaxWidth()
        )
    }
}

Bottom Sheet with Action Buttons

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Bottom Sheet with Actions",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Action Sheet",
        startAction = {
            val dismiss = LocalDismissState.current
            TextButton(
                text = "Cancel",
                onClick = { dismiss?.invoke() }
            )
        },
        endAction = {
            val dismiss = LocalDismissState.current
            TextButton(
                text = "Confirm",
                onClick = { dismiss?.invoke() },
                colors = ButtonDefaults.textButtonColorsPrimary()
            )
        },
        onDismissRequest = { showBottomSheet = false }
    ) {
        Text("Content with custom header actions")
        Spacer(modifier = Modifier.height(16.dp))
        Text("Start and end action buttons are displayed in the header")
    }
}

Bottom Sheet with Form

kotlin
var showBottomSheet by remember { mutableStateOf(false) }
var textFieldValue by remember { mutableStateOf("") }
var switchState by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Form Bottom Sheet",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Settings Form",
        onDismissRequest = { showBottomSheet = false }
    ) {
        Card(
            colors = CardDefaults.defaultColors(
                color = MiuixTheme.colorScheme.secondaryContainer,
            ),
        ) {
            TextField(
                modifier = Modifier.padding(vertical = 12.dp),
                value = textFieldValue,
                label = "Enter content",
                maxLines = 1,
                onValueChange = { textFieldValue = it }
            )
            
            SuperSwitch(
                title = "Switch Option",
                checked = switchState,
                onCheckedChange = { switchState = it }
            )
        }
        
        Spacer(Modifier.height(12.dp))
        
        Row(
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            TextButton(
                text = "Cancel",
                onClick = { showBottomSheet = false },
                modifier = Modifier.weight(1f)
            )
            Spacer(Modifier.width(20.dp))
            TextButton(
                text = "Confirm",
                onClick = { showBottomSheet = false },
                modifier = Modifier.weight(1f),
                colors = ButtonDefaults.textButtonColorsPrimary()
            )
        }
    }
}

Adaptive Content Height

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Adaptive Height Bottom Sheet",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Adaptive Height",
        onDismissRequest = { showBottomSheet = false }
    ) {
        Column(modifier = Modifier.padding(vertical = 16.dp)) {
            Text("The height adapts to content")
            Spacer(modifier = Modifier.height(16.dp))
            Text("Add as much content as needed")
            Spacer(modifier = Modifier.height(16.dp))
            Text("But will not cover the status bar area")
            Spacer(modifier = Modifier.height(16.dp))
            TextButton(
                text = "Close",
                onClick = { showBottomSheet = false },
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

Non-Dismissible Bottom Sheet

kotlin
var showBottomSheet by remember { mutableStateOf(false) }

Scaffold {
    TextButton(
        text = "Show Non-Dismissible Bottom Sheet",
        onClick = { showBottomSheet = true }
    )

    SuperBottomSheet(
        show = showBottomSheet,
        title = "Non-Dismissible",
        allowDismiss = false,
        onDismissRequest = { showBottomSheet = false }
    ) {
        Column(modifier = Modifier.padding(vertical = 16.dp)) {
            Text("This bottom sheet cannot be dismissed by dragging or back gesture")
            Spacer(modifier = Modifier.height(16.dp))
            Text("You must explicitly close it using the button below")
            Spacer(modifier = Modifier.height(16.dp))
            TextButton(
                text = "Close",
                onClick = { showBottomSheet = false },
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

Changelog

Released under the Apache-2.0 License