Skip to content

#! /usr/bin/env markdown

Snackbar ​

Snackbar is a lightweight feedback component in Miuix used to display brief messages at the bottom of the screen. It can optionally provide actions such as “Undo” and supports different display durations.

Import ​

kotlin
import top.yukonga.miuix.kmp.basic.Snackbar
import top.yukonga.miuix.kmp.basic.SnackbarHost
import top.yukonga.miuix.kmp.basic.SnackbarHostState
import top.yukonga.miuix.kmp.basic.SnackbarDuration
import top.yukonga.miuix.kmp.basic.SnackbarResult

Basic Usage ​

The Snackbar is usually used together with Scaffold. You create a SnackbarHostState, pass it to SnackbarHost, and then call showSnackbar to display messages:a

kotlin
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

Scaffold(
    snackbarHost = {
        SnackbarHost(state = snackbarHostState)
    },
) { paddingValues ->
    Box(
        modifier = Modifier
            .padding(paddingValues),
    ) {
        TextButton(
            text = "Show message",
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("This is a short message")
                }
            },
        )
    }
}

SnackbarHostState and showSnackbar ​

SnackbarHostState manages a queue of Snackbar messages.

showSnackbar ​

kotlin
suspend fun SnackbarHostState.showSnackbar(
    message: String,
    actionLabel: String? = null,
    withDismissAction: Boolean = false,
    duration: SnackbarDuration = SnackbarDuration.Short,
): SnackbarResult
Parameter NameTypeDescriptionDefault ValueRequired
messageStringText shown in the Snackbar-Yes
actionLabelString?Optional label for the action buttonnullNo
withDismissActionBooleanWhether to show a dismiss iconfalseNo
durationSnackbarDurationDuration that the Snackbar stays visibleSnackbarDuration.ShortNo

The return value SnackbarResult indicates whether the Snackbar was dismissed or the action was performed.

Getting the oldest or newest Snackbar ​

kotlin
suspend fun SnackbarHostState.newestSnackbarData(): SnackbarData?
suspend fun SnackbarHostState.oldestSnackbarData(): SnackbarData?

These helpers allow you to manually dismiss the newest or oldest visible Snackbar via dismiss() or performAction().

SnackbarHost ​

SnackbarHost is responsible for rendering the Snackbars based on the given SnackbarHostState.

kotlin
@Composable
fun SnackbarHost(
    state: SnackbarHostState,
    modifier: Modifier = Modifier,
    canSwipeToDismiss: Boolean = true,
    content: @Composable (SnackbarData) -> Unit = { Snackbar(it) },
)
Parameter NameTypeDescriptionDefault ValueRequired
stateSnackbarHostStateState that holds the Snackbar queue-Yes
modifierModifierModifier applied to the host containerModifierNo
canSwipeToDismissBooleanWhether Snackbars can be dismissed by swipetrueNo
content@Composable (SnackbarData) -> UnitCustom content for each Snackbar item{ Snackbar(it) }No

In most cases you can keep the default content which uses the built‑in Snackbar composable.

Snackbar ​

Snackbar defines the default visual style for messages.

kotlin
@Composable
fun Snackbar(
    data: SnackbarData,
    modifier: Modifier = Modifier,
    cornerRadius: Dp = SnackbarDefaults.CornerRadius,
    colors: SnackbarColors = SnackbarDefaults.snackbarColors(),
    insideMargin: PaddingValues = SnackbarDefaults.InsideMargin,
)
Parameter NameTypeDescriptionDefault ValueRequired
dataSnackbarDataData describing message and actions-Yes
modifierModifierModifier applied to the Snackbar containerModifierNo
cornerRadiusDpCorner radius of the SnackbarSnackbarDefaults.CornerRadiusNo
colorsSnackbarColorsColor configuration for the SnackbarSnackbarDefaults.snackbarColors()No
insideMarginPaddingValuesInner padding of the Snackbar contentSnackbarDefaults.InsideMarginNo

SnackbarColors and SnackbarDefaults ​

SnackbarColors defines the color set used by the Snackbar:

kotlin
data class SnackbarColors(
    val containerColor: Color,
    val contentColor: Color,
    val actionContentColor: Color,
    val dismissActionContentColor: Color,
    val actionContainerColor: Color,
)

You can create a color configuration via SnackbarDefaults.snackbarColors:

kotlin
val colors = SnackbarDefaults.snackbarColors(
    containerColor = MiuixTheme.colorScheme.onSecondaryVariant,
    contentColor = MiuixTheme.colorScheme.secondaryVariant,
    actionContentColor = MiuixTheme.colorScheme.onPrimary,
    dismissActionContentColor = MiuixTheme.colorScheme.onSurfaceContainerVariant,
    actionContainerColor = MiuixTheme.colorScheme.primary,
)

By default the Snackbar uses an inverse surface tone (a dark bar in light theme, a light bar in dark theme) so it stands out over the content behind it.

The action label is rendered as a filled pill; actionContainerColor is its background and actionContentColor its text color, so override them together to keep enough contrast.

Constants ​

SnackbarDefaults also exposes the default dimensions and paddings used by Snackbar:

Constant NameTypeDescriptionDefault Value
CornerRadiusDpDefault corner radius of the Snackbar16.dp
InsideMarginPaddingValuesDefault inner padding of the Snackbar contentPaddingValues(all = 12.dp)
OuterPaddingPaddingValuesDefault outer padding around the SnackbarPaddingValues(start = 12.dp, end = 12.dp, top = 8.dp)
ActionCornerRadiusDpDefault corner radius of the action pill50.dp
ActionInsideMarginPaddingValuesDefault inner padding of the action pillPaddingValues(horizontal = 12.dp, vertical = 0.dp)

SnackbarDuration and SnackbarResult ​

SnackbarDuration ​

SnackbarDuration controls how long the Snackbar stays visible:

kotlin
sealed interface SnackbarDuration {
    data object Short : SnackbarDuration
    data object Long : SnackbarDuration
    data object Indefinite : SnackbarDuration
    data class Custom(val durationMillis: Long) : SnackbarDuration
}
OptionDescriptionDuration
ShortShort messageAbout 4 seconds
LongLonger messageAbout 10 seconds
IndefiniteStays until dismissed or action firedUntil dismissed
CustomCustom duration in millisecondsUser‑specified

SnackbarResult ​

SnackbarResult describes how the Snackbar was completed:

kotlin
enum class SnackbarResult {
    Dismissed,
    ActionPerformed,
}

Advanced Usage ​

Snackbar with action ​

kotlin
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

TextButton(
    text = "Show action",
    onClick = {
        scope.launch {
            val result = snackbarHostState.showSnackbar(
                message = "This message has an action",
                actionLabel = "Undo",
                duration = SnackbarDuration.Short,
            )
            when (result) {
                SnackbarResult.ActionPerformed -> { /* handle undo */ }
                SnackbarResult.Dismissed -> { /* handle timeout */ }
            }
        }
    },
)

Dismissible and indefinite Snackbar ​

kotlin
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

TextButton(
    text = "Show indefinite",
    onClick = {
        scope.launch {
            snackbarHostState.showSnackbar(
                message = "Indefinite message, dismiss manually",
                withDismissAction = true,
                duration = SnackbarDuration.Indefinite,
            )
        }
    },
)

TextButton(
    text = "Dismiss oldest",
    onClick = {
        scope.launch {
            snackbarHostState.oldestSnackbarData()?.dismiss()
        }
    },
)

Changelog

Released under the Apache-2.0 License