An onClick lambda cannot call a composable such as LaunchedEffect. For work the user starts, rememberCoroutineScope() returns a scope that is cancelled when its call site leaves:
Button(onClick = {
scope.launch { // started by an event, not by composition
Log.d(FX, "snackbar: show")
try {
val result = snackbar.showSnackbar("Added to cart", actionLabel = "Undo")
Log.d(FX, "snackbar: $result")
} catch (e: CancellationException) { Log.d(FX, "snackbar: cancelled"); throw e }
}
}) { Text("Add to cart") }Add to cart, five seconds, Undo; then Add to cart and Close panel, which removes the panel:
D/BookNestFx: snackbar: show D/BookNestFx: snackbar: ActionPerformed D/BookNestFx: snackbar: show D/BookNestFx: snackbar: cancelled
With an action label the snackbar waits indefinitely; closing the panel cancelled it. Work that must outlive the screen belongs in viewModelScope (ViewModel and UDF).