Build apps faster with our new App builder! Check it out →

Snackbar

Common

Component in Material 3 Compose

Snackbars provide brief messages about app processes at the bottom of the screen.

Snackbar
image

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material3:material3:1.4.0-alpha02")
}

Overloads

@Composable
fun Snackbar(
    modifier: Modifier = Modifier,
    action: @Composable (() -> Unit)? = null,
    dismissAction: @Composable (() -> Unit)? = null,
    actionOnNewLine: Boolean = false,
    shape: Shape = SnackbarDefaults.shape,
    containerColor: Color = SnackbarDefaults.color,
    contentColor: Color = SnackbarDefaults.contentColor,
    actionContentColor: Color = SnackbarDefaults.actionContentColor,
    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor,
    content: @Composable () -> Unit
)

Parameters

namedescription
modifierthe [Modifier] to be applied to this snackbar
actionaction / button component to add as an action to the snackbar. Consider using [ColorScheme.inversePrimary] as the color for the action, if you do not have a predefined color you wish to use instead.
dismissActionaction / button component to add as an additional close affordance action when a snackbar is non self-dismissive. Consider using [ColorScheme.inverseOnSurface] as the color for the action, if you do not have a predefined color you wish to use instead.
actionOnNewLinewhether or not action should be put on a separate line. Recommended for action with long action text.
shapedefines the shape of this snackbar's container
containerColorthe color used for the background of this snackbar. Use [Color.Transparent] to have no color.
contentColorthe preferred color for content inside this snackbar
actionContentColorthe preferred content color for the optional [action] inside this snackbar
dismissActionContentColorthe preferred content color for the optional [dismissAction] inside this snackbar
contentcontent to show information about a process that an app has performed or will perform
@Composable
fun Snackbar(
    snackbarData: SnackbarData,
    modifier: Modifier = Modifier,
    actionOnNewLine: Boolean = false,
    shape: Shape = SnackbarDefaults.shape,
    containerColor: Color = SnackbarDefaults.color,
    contentColor: Color = SnackbarDefaults.contentColor,
    actionColor: Color = SnackbarDefaults.actionColor,
    actionContentColor: Color = SnackbarDefaults.actionContentColor,
    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor,
)

Parameters

namedescription
snackbarDatadata about the current snackbar showing via [SnackbarHostState]
modifierthe [Modifier] to be applied to this snackbar
actionOnNewLinewhether or not action should be put on a separate line. Recommended for action with long action text.
shapedefines the shape of this snackbar's container
containerColorthe color used for the background of this snackbar. Use [Color.Transparent] to have no color.
contentColorthe preferred color for content inside this snackbar
actionColorthe color of the snackbar's action
actionContentColorthe preferred content color for the optional action inside this snackbar. See [SnackbarVisuals.actionLabel].
dismissActionContentColorthe preferred content color for the optional dismiss action inside this snackbar. See [SnackbarVisuals.withDismissAction].

Code Examples

ScaffoldWithSimpleSnackbar

@Preview
@Composable
fun ScaffoldWithSimpleSnackbar() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = { SnackbarHost(snackbarHostState) },
        floatingActionButton = {
            var clickCount by remember { mutableStateOf(0) }
            ExtendedFloatingActionButton(
                onClick = {
                    // show snackbar as a suspend function
                    scope.launch { snackbarHostState.showSnackbar("Snackbar # ${++clickCount}") }
                }
            ) {
                Text("Show snackbar")
            }
        },
        content = { innerPadding ->
            Text(
                text = "Body content",
                modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
            )
        }
    )
}

ScaffoldWithCustomSnackbar

@Preview
@Composable
fun ScaffoldWithCustomSnackbar() {
    class SnackbarVisualsWithError(override val message: String, val isError: Boolean) :
        SnackbarVisuals {
        override val actionLabel: String
            get() = if (isError) "Error" else "OK"

        override val withDismissAction: Boolean
            get() = false

        override val duration: SnackbarDuration
            get() = SnackbarDuration.Indefinite
    }

    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = {
            // reuse default SnackbarHost to have default animation and timing handling
            SnackbarHost(snackbarHostState) { data ->
                // custom snackbar with the custom action button color and border
                val isError = (data.visuals as? SnackbarVisualsWithError)?.isError ?: false
                val buttonColor =
                    if (isError) {
                        ButtonDefaults.textButtonColors(
                            containerColor = MaterialTheme.colorScheme.errorContainer,
                            contentColor = MaterialTheme.colorScheme.error
                        )
                    } else {
                        ButtonDefaults.textButtonColors(
                            contentColor = MaterialTheme.colorScheme.inversePrimary
                        )
                    }

                Snackbar(
                    modifier =
                        Modifier.border(2.dp, MaterialTheme.colorScheme.secondary).padding(12.dp),
                    action = {
                        TextButton(
                            onClick = { if (isError) data.dismiss() else data.performAction() },
                            colors = buttonColor
                        ) {
                            Text(data.visuals.actionLabel ?: "")
                        }
                    }
                ) {
                    Text(data.visuals.message)
                }
            }
        },
        floatingActionButton = {
            var clickCount by remember { mutableStateOf(0) }
            ExtendedFloatingActionButton(
                onClick = {
                    scope.launch {
                        snackbarHostState.showSnackbar(
                            SnackbarVisualsWithError(
                                "Snackbar # ${++clickCount}",
                                isError = clickCount % 2 != 0
                            )
                        )
                    }
                }
            ) {
                Text("Show snackbar")
            }
        },
        content = { innerPadding ->
            Text(
                text = "Custom Snackbar Demo",
                modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
            )
        }
    )
}

ScaffoldWithMultilineSnackbar

@Preview
@Composable
fun ScaffoldWithMultilineSnackbar() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = {
            SnackbarHost(snackbarHostState) { data ->
                Snackbar {
                    // The Material spec recommends a maximum of 2 lines of text.
                    Text(data.visuals.message, maxLines = 2, overflow = TextOverflow.Ellipsis)
                }
            }
        },
        floatingActionButton = {
            ExtendedFloatingActionButton(
                onClick = {
                    scope.launch {
                        val longMessage =
                            "Very very very very very very very very very very very very very " +
                                "very very very very very very very very very very very very " +
                                "very very very very very very very very very very long message"
                        snackbarHostState.showSnackbar(longMessage)
                    }
                }
            ) {
                Text("Show snackbar")
            }
        },
        content = { innerPadding ->
            Text(
                text = "Multiline Snackbar Demo",
                modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
            )
        }
    )
}

ScaffoldWithIndefiniteSnackbar

@Preview
@Composable
fun ScaffoldWithIndefiniteSnackbar() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = { SnackbarHost(snackbarHostState) },
        floatingActionButton = {
            var clickCount by remember { mutableStateOf(0) }
            ExtendedFloatingActionButton(
                onClick = {
                    // show snackbar as a suspend function
                    scope.launch {
                        snackbarHostState.showSnackbar(
                            message = "Snackbar # ${++clickCount}",
                            actionLabel = "Action",
                            withDismissAction = true,
                            duration = SnackbarDuration.Indefinite
                        )
                    }
                }
            ) {
                Text("Show snackbar")
            }
        },
        content = { innerPadding ->
            Text(
                text = "Body content",
                modifier = Modifier.padding(innerPadding).fillMaxSize().wrapContentSize()
            )
        }
    )
}
by @alexstyl