
Flexible, customizable snackbar system featuring swipe-to-dismiss, geometric stacking visuals, configurable animations, durations and alignment, plus an easy host/state API for transient message management.
A flexible and customizable snackbar library for Compose Multiplatform with support for Android, iOS, Desktop (JVM), Web (JS), and WebAssembly.
| Platform | Supported | Minimum Version |
|---|---|---|
| Android | ✅ | API 24 |
| iOS | ✅ | iOS 15.0 |
| Desktop | ✅ | JVM 11 |
| Web JS | ✅ | - |
| Wasm | ✅ | - |
AnchoredDraggableState
Add the dependency to your commonMain source set:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("dev.stetsiuk:compose-snackbar:1.0.0")
}
}
}Wrap your app content with ProvideSnackBarHost:
@Composable
fun App() {
val snackbarState = rememberSnackBarHostState()
ProvideSnackBarHost(state = snackbarState) {
MaterialTheme {
// Your app content
YourScreen()
}
}
}Access the SnackBarHostState and show a snackbar:
@Composable
fun YourScreen() {
val snackbarState = LocalSnackBarHostState.current
Button(onClick = {
val state = SnackBarState()
val data = SnackBarData(state) {
BasicSnackBar(
color = Color.Black,
modifier = Modifier.padding(horizontal = 16.dp)
) {
Text("Request timeout", modifier = Modifier.padding(16.dp))
}
}
snackbarState.show(data)
}) {
Text("Show Snackbar")
}
}Create a custom snackbar using BasicDraggableSnackBar:
fun SnackBarHostState.show(text: String) {
val state = SnackBarState()
val data = SnackBarData(state) {
BasicDraggableSnackBar(
modifier = Modifier.padding(horizontal = 16.dp),
color = Color.Black,
onDismissed = { state.hide() }
) {
Row(
modifier = Modifier.padding(16.dp, 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.weight(1f),
text = text,
color = Color.White
)
IconButton(onClick = { state.hide() }) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close",
tint = Color.White
)
}
}
}
}
show(data)
}Customize the stacking effect with SnackBarStackParams:
ProvideSnackBarHost(
state = snackbarState,
stackParams = SnackBarStackParams(
scaleRatio = 0.95f,
alphaRatio = 0.85f,
offsetStep = (-8).dp,
maxVisibleItems = 3
)
) {
// Your content
}Configure enter/exit transitions:
ProvideSnackBarHost(
state = snackbarState,
enter = fadeIn() + scaleIn(initialScale = 0.9f),
exit = fadeOut() + shrinkOut()
) {
// Your content
}Position snackbars anywhere on the screen:
ProvideSnackBarHost(
state = snackbarState,
contentAlignment = Alignment.TopCenter
) {
// Your content
}Set custom display duration:
val data = SnackBarData(
state = SnackBarState(),
duration = SnackBarData.Duration.Long // Short (2s), Long (3.5s), or Custom
) {
// Your snackbar content
}
snackbarState.show(data)Main composable that manages snackbar lifecycle and rendering.
Parameters:
modifier: Modifier - Modifier for the host containerstate: SnackBarHostState - State holder for snackbar managementcontentPadding: PaddingValues - Padding around snackbar areacontentAlignment: Alignment - Position of snackbars on screenenter: EnterTransition - Animation for showing snackbarsexit: ExitTransition - Animation for hiding snackbarsstackParams: SnackBarStackParams - Configuration for stack visualizationcontent: @Composable () -> Unit - Your app contentA snackbar with built-in swipe-to-dismiss functionality.
Parameters:
color: Color - Background colormodifier: Modifier - Modifier for customizationshape: Shape - Shape of the snackbar (default: RoundedCornerShape(16.dp))contentColor: Color - Color for content (default: White)border: BorderStroke? - Optional borderonDismissed: () -> Unit - Callback when dismissed via swipecontent: @Composable () -> Unit - Snackbar contentA simple snackbar without gesture handling.
Parameters:
color: Color - Background colormodifier: Modifier - Modifier for customizationshape: Shape - Shape of the snackbarcontentColor: Color - Color for contentborder: BorderStroke? - Optional bordercontent: @Composable () -> Unit - Snackbar contentState holder for managing snackbars.
Methods:
show(data: SnackBarData) - Show a snackbarhide(id: String) - Hide a specific snackbar by IDIndividual snackbar state.
Methods:
show() - Show this snackbarhide() - Hide this snackbarRepresents a single snackbar.
Parameters:
state: SnackBarState - State for this snackbarid: String - Unique identifier (auto-generated)duration: Duration - Display durationcontent: @Composable () -> Unit - Snackbar contentConfiguration for stack visualization.
Parameters:
scaleRatio: Float - Base ratio for geometric scale progression (default: 0.95)alphaRatio: Float - Base ratio for geometric alpha progression (default: 0.85)offsetStep: Dp - Vertical offset between items (default: -8.dp)maxVisibleItems: Int - Maximum visible snackbars (default: 3)Check out the composeApp module for a complete working example with different customization options.
Contributions are welcome! Please feel free to submit a Pull Request.
Copyright 2025 Vasyl Stetsiuk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Vasyl Stetsiuk
Built with Compose Multiplatform by JetBrains.
A flexible and customizable snackbar library for Compose Multiplatform with support for Android, iOS, Desktop (JVM), Web (JS), and WebAssembly.
| Platform | Supported | Minimum Version |
|---|---|---|
| Android | ✅ | API 24 |
| iOS | ✅ | iOS 15.0 |
| Desktop | ✅ | JVM 11 |
| Web JS | ✅ | - |
| Wasm | ✅ | - |
AnchoredDraggableState
Add the dependency to your commonMain source set:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("dev.stetsiuk:compose-snackbar:1.0.0")
}
}
}Wrap your app content with ProvideSnackBarHost:
@Composable
fun App() {
val snackbarState = rememberSnackBarHostState()
ProvideSnackBarHost(state = snackbarState) {
MaterialTheme {
// Your app content
YourScreen()
}
}
}Access the SnackBarHostState and show a snackbar:
@Composable
fun YourScreen() {
val snackbarState = LocalSnackBarHostState.current
Button(onClick = {
val state = SnackBarState()
val data = SnackBarData(state) {
BasicSnackBar(
color = Color.Black,
modifier = Modifier.padding(horizontal = 16.dp)
) {
Text("Request timeout", modifier = Modifier.padding(16.dp))
}
}
snackbarState.show(data)
}) {
Text("Show Snackbar")
}
}Create a custom snackbar using BasicDraggableSnackBar:
fun SnackBarHostState.show(text: String) {
val state = SnackBarState()
val data = SnackBarData(state) {
BasicDraggableSnackBar(
modifier = Modifier.padding(horizontal = 16.dp),
color = Color.Black,
onDismissed = { state.hide() }
) {
Row(
modifier = Modifier.padding(16.dp, 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.weight(1f),
text = text,
color = Color.White
)
IconButton(onClick = { state.hide() }) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close",
tint = Color.White
)
}
}
}
}
show(data)
}Customize the stacking effect with SnackBarStackParams:
ProvideSnackBarHost(
state = snackbarState,
stackParams = SnackBarStackParams(
scaleRatio = 0.95f,
alphaRatio = 0.85f,
offsetStep = (-8).dp,
maxVisibleItems = 3
)
) {
// Your content
}Configure enter/exit transitions:
ProvideSnackBarHost(
state = snackbarState,
enter = fadeIn() + scaleIn(initialScale = 0.9f),
exit = fadeOut() + shrinkOut()
) {
// Your content
}Position snackbars anywhere on the screen:
ProvideSnackBarHost(
state = snackbarState,
contentAlignment = Alignment.TopCenter
) {
// Your content
}Set custom display duration:
val data = SnackBarData(
state = SnackBarState(),
duration = SnackBarData.Duration.Long // Short (2s), Long (3.5s), or Custom
) {
// Your snackbar content
}
snackbarState.show(data)Main composable that manages snackbar lifecycle and rendering.
Parameters:
modifier: Modifier - Modifier for the host containerstate: SnackBarHostState - State holder for snackbar managementcontentPadding: PaddingValues - Padding around snackbar areacontentAlignment: Alignment - Position of snackbars on screenenter: EnterTransition - Animation for showing snackbarsexit: ExitTransition - Animation for hiding snackbarsstackParams: SnackBarStackParams - Configuration for stack visualizationcontent: @Composable () -> Unit - Your app contentA snackbar with built-in swipe-to-dismiss functionality.
Parameters:
color: Color - Background colormodifier: Modifier - Modifier for customizationshape: Shape - Shape of the snackbar (default: RoundedCornerShape(16.dp))contentColor: Color - Color for content (default: White)border: BorderStroke? - Optional borderonDismissed: () -> Unit - Callback when dismissed via swipecontent: @Composable () -> Unit - Snackbar contentA simple snackbar without gesture handling.
Parameters:
color: Color - Background colormodifier: Modifier - Modifier for customizationshape: Shape - Shape of the snackbarcontentColor: Color - Color for contentborder: BorderStroke? - Optional bordercontent: @Composable () -> Unit - Snackbar contentState holder for managing snackbars.
Methods:
show(data: SnackBarData) - Show a snackbarhide(id: String) - Hide a specific snackbar by IDIndividual snackbar state.
Methods:
show() - Show this snackbarhide() - Hide this snackbarRepresents a single snackbar.
Parameters:
state: SnackBarState - State for this snackbarid: String - Unique identifier (auto-generated)duration: Duration - Display durationcontent: @Composable () -> Unit - Snackbar contentConfiguration for stack visualization.
Parameters:
scaleRatio: Float - Base ratio for geometric scale progression (default: 0.95)alphaRatio: Float - Base ratio for geometric alpha progression (default: 0.85)offsetStep: Dp - Vertical offset between items (default: -8.dp)maxVisibleItems: Int - Maximum visible snackbars (default: 3)Check out the composeApp module for a complete working example with different customization options.
Contributions are welcome! Please feel free to submit a Pull Request.
Copyright 2025 Vasyl Stetsiuk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Vasyl Stetsiuk
Built with Compose Multiplatform by JetBrains.