Skip to main content
Snackbar provides brief feedback about an operation through a message at the bottom of the screen. Snackbars can contain an action button and are temporary by default.

Usage

import com.nomanr.lumo.ui.components.snackbar.Snackbar
import com.nomanr.lumo.ui.components.snackbar.SnackbarHost

val snackbarHostState = remember { SnackbarHostState() }

// Show snackbar
scope.launch {
    snackbarHostState.showSnackbar(
        message = "Item deleted",
        actionLabel = "Undo"
    )
}

// Display snackbar
SnackbarHost(hostState = snackbarHostState)

Variants

Simple Snackbar

Basic message without action:
Snackbar(
    modifier = Modifier,
    content = {
        Text("Changes saved successfully")
    }
)

Snackbar with Action

Include an action button:
Snackbar(
    modifier = Modifier,
    action = {
        Text(
            text = "UNDO",
            modifier = Modifier.clickable { /* Handle action */ }
        )
    },
    content = {
        Text("Item deleted")
    }
)

Snackbar with Dismiss Action

Add a dismiss button:
Snackbar(
    modifier = Modifier,
    action = {
        Text("UNDO", modifier = Modifier.clickable { })
    },
    dismissAction = {
        IconButton(onClick = { /* Dismiss */ }) {
            Icon(Icons.Default.Close, "Dismiss")
        }
    },
    content = {
        Text("Message sent")
    }
)

Using SnackbarData

With Material’s SnackbarHostState:
val snackbarHostState = remember { SnackbarHostState() }

SnackbarHost(snackbarHostState) { data ->
    Snackbar(
        snackbarData = data,
        containerColor = AppTheme.colors.primary,
        contentColor = AppTheme.colors.onPrimary
    )
}

// Trigger snackbar
scope.launch {
    val result = snackbarHostState.showSnackbar(
        message = "Operation completed",
        actionLabel = "View",
        withDismissAction = true
    )
    
    when (result) {
        SnackbarResult.ActionPerformed -> { /* Handle action */ }
        SnackbarResult.Dismissed -> { /* Handle dismiss */ }
    }
}

Parameters

Snackbar (with SnackbarData)

snackbarData
SnackbarData
required
Data object containing the snackbar message and actions
modifier
Modifier
default:"Modifier"
Modifier for the snackbar container
shape
Shape
default:"RoundedCornerShape(12.dp)"
The shape of the snackbar
containerColor
Color
default:"AppTheme.colors.primary"
Background color of the snackbar
contentColor
Color
default:"AppTheme.colors.onPrimary"
Color for the message text
actionColor
Color
default:"AppTheme.colors.onPrimary"
Background color for the action button
actionContentColor
Color
default:"AppTheme.colors.primary"
Text color for the action button
dismissActionContentColor
Color
default:"AppTheme.colors.onPrimary"
Color for the dismiss action

Snackbar (Custom)

modifier
Modifier
default:"Modifier"
Modifier for the snackbar container
action
@Composable (() -> Unit)?
default:"null"
Optional action button content
dismissAction
@Composable (() -> Unit)?
default:"null"
Optional dismiss button content
shape
Shape
default:"RoundedCornerShape(12.dp)"
The shape of the snackbar
containerColor
Color
default:"AppTheme.colors.primary"
Background color of the snackbar
contentColor
Color
default:"AppTheme.colors.onPrimary"
Color for the message text
actionContentColor
Color
default:"AppTheme.colors.primary"
Text color for the action button
dismissActionContentColor
Color
default:"AppTheme.colors.onPrimary"
Color for the dismiss action
content
@Composable () -> Unit
required
The message content to display

Styling

Custom Colors

Snackbar(
    containerColor = Color(0xFF323232),
    contentColor = Color.White,
    content = { Text("Dark themed snackbar") }
)

Custom Shape

Snackbar(
    shape = RoundedCornerShape(8.dp),
    content = { Text("Custom rounded corners") }
)

Layout Specifications

The snackbar has the following layout specifications:
  • Container Max Width: 600.dp
  • Single Line Height: 56.dp
  • Two Lines Height: 68.dp
  • Horizontal Spacing: 16.dp
  • Horizontal Spacing (Button Side): 8.dp
  • Vertical Padding: 6.dp
  • Elevation: 8.dp
  • Default Shape: RoundedCornerShape(12.dp)

Best Practices

  1. Brief Messages: Keep messages short and actionable
  2. Single Action: Include at most one action button
  3. Action Labels: Use short, action-oriented labels like “UNDO”, “VIEW”, “RETRY”
  4. Duration: Let snackbars auto-dismiss after a few seconds
  5. Positioning: Display at the bottom of the screen, above navigation bars
  6. Frequency: Don’t show multiple snackbars simultaneously
  7. Accessibility: Ensure action buttons are easily tappable (min 44dp height)

Integration with SnackbarHost

For proper snackbar management in your app:
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState) { data ->
            Snackbar(
                snackbarData = data,
                modifier = Modifier.padding(16.dp)
            )
        }
    }
) {
    // Your content
    Button(
        onClick = {
            scope.launch {
                snackbarHostState.showSnackbar("Action completed")
            }
        }
    ) {
        Text("Show Snackbar")
    }
}

Source Reference

See the full implementation in Snackbar.kt:44-97 and Snackbar.kt:100-131.

Build docs developers (and LLMs) love