🍞 A powerful and elegant toast notification library for Compose Multiplatform with gestures, animations, and theming support.
- 🎯 Snackbar-style API - Familiar API similar to Material3 Snackbar
- 📚 Stacked Toasts - Display multiple toasts with smooth animations
- 👆 Gesture Support - Tap to pause, swipe to dismiss
- 🎨 Category-based Theming - Success, Error, Warning, General, and Custom categories
- ⏱️ Auto-dismiss - Configurable auto-dismiss with pause on interaction
- 🎭 Smooth Animations - Spring-based animations for natural feel
- 📱 Compose Multiplatform - Android, iOS, Desktop, and Web support
- 🔧 Highly Customizable - Custom themes, colors, shapes, and icons
- 🏗️ Easy Integration - Works seamlessly with Material3 Scaffold
@Composable
fun App() {
val toastHostState = rememberToastHostState()
val scope = rememberCoroutineScope()
ToastScaffold(
toastHost = { ToastHost(hostState = toastHostState) }
) { paddingValues ->
Button(
onClick = {
scope.launch {
toastHostState.showToast(
message = "Hello, Toast!",
category = ToastCategory.Success
)
}
}
) {
Text("Show Toast")
}
}
}Add the dependency below to your module's build.gradle file:
dependencies {
implementation("io.github.androidpoet:dhyantoast:$version")
}Add the dependency below to your module's build.gradle.kts file:
sourceSets {
commonMain.dependencies {
implementation("io.github.androidpoet:dhyantoast:$version")
}
}Or using the older syntax:
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.androidpoet:dhyantoast:$version")
}
}
}DhyānToast follows the same pattern as Material3's Snackbar API, making it familiar and easy to use.
@Composable
fun MyApp() {
// 1. Create toast host state
val toastHostState = rememberToastHostState()
val scope = rememberCoroutineScope()
// 2. Use ToastScaffold instead of regular Scaffold
ToastScaffold(
toastHost = {
ToastHost(
hostState = toastHostState,
alignment = ToastAlignment.Bottom,
autoDismissEnabled = true,
autoDismissDelay = 3000L
)
}
) { paddingValues ->
// Your content here
Button(
onClick = {
scope.launch {
// 3. Show toasts from coroutines
toastHostState.showToast(
message = "Operation completed!",
category = ToastCategory.Success
)
}
}
) {
Text("Show Toast")
}
}
}// Success toast
toastHostState.showToast(
message = "Operation completed successfully!",
title = "Success",
category = ToastCategory.Success
)
// Error toast
toastHostState.showToast(
message = "Something went wrong!",
title = "Error",
category = ToastCategory.Error
)
// Warning toast
toastHostState.showToast(
message = "Please check your input",
title = "Warning",
category = ToastCategory.Warning
)
// General/Info toast
toastHostState.showToast(
message = "Here's some useful information",
category = ToastCategory.General
)
// Custom category
toastHostState.showToast(
message = "Custom notification",
category = ToastCategory.Custom("analytics")
)val toastTheme = ToastTheme(
success = ToastCategoryStyle(
backgroundColor = Color(0xFF4CAF50),
textColor = Color.White,
icon = Icons.Default.Check
),
error = ToastCategoryStyle(
backgroundColor = Color(0xFFF44336),
textColor = Color.White,
icon = Icons.Default.Close
),
warning = ToastCategoryStyle(
backgroundColor = Color(0xFFFF9800),
textColor = Color.White,
icon = Icons.Default.Warning
)
)
ToastHost(
hostState = toastHostState,
theme = toastTheme,
showCloseButton = true,
alignment = ToastAlignment.Top,
visibleCount = 3
)ToastHost(
hostState = toastHostState,
alignment = ToastAlignment.Top, // Top or Bottom
autoDismissEnabled = true, // Auto-dismiss toasts
autoDismissDelay = 3000L, // 3 seconds
visibleCount = 3, // Max visible toasts in stack
categories = listOf( // Filter specific categories
ToastCategory.Success,
ToastCategory.Error
),
maxWidth = 400.dp, // Max width on larger screens
contentPadding = PaddingValues(16.dp), // Padding around toasts
showCloseButton = true, // Show close button
theme = toastTheme // Custom theme
)You can provide your own toast composable for completely custom UI:
ToastHost(
hostState = toastHostState,
toast = { toastData ->
// Your custom toast UI
Surface(
modifier = Modifier.fillMaxWidth().padding(8.dp),
shape = RoundedCornerShape(16.dp),
color = MaterialTheme.colorScheme.primary
) {
Row(modifier = Modifier.padding(16.dp)) {
Text(
text = toastData.message,
color = MaterialTheme.colorScheme.onPrimary
)
}
}
}
)// Clear all toasts
toastHostState.clearAll()
// Dismiss a specific toast
toastData.dismiss()DhyānToast supports intuitive gesture-based interactions:
- Tap any toast to pause auto-dismiss for all toasts
- Toasts will expand to show all visible items in the stack
- Tap again to resume auto-dismiss
- Swipe up (when aligned to top) to dismiss a toast
- Swipe down (when aligned to bottom) to dismiss a toast
- Smooth spring-based animations follow your finger
- Optional close button (×) on each toast
- Enable with
showCloseButton = true
- Spring-based animations for natural feel
- Smooth stacking animations when toasts appear/disappear
- Fade and scale effects for visual polish
- Configurable dampingRatio and stiffness for custom feel
DhyānToast works on all Compose Multiplatform targets:
| Platform | Status |
|---|---|
| Android | ✅ Supported |
| iOS | ✅ Supported |
| Desktop (JVM) | ✅ Supported |
| Web (JS/WASM) | ✅ Supported |
| macOS | ✅ Supported |
While both use similar APIs, they serve different purposes:
| Feature | DhyānToast | Material3 Snackbar |
|---|---|---|
| Multiple notifications | ✅ Stacked toasts | ❌ One at a time |
| Gesture interactions | ✅ Tap to pause, swipe to dismiss | ❌ Limited |
| Auto-dismiss | ✅ Configurable per toast | |
| Category theming | ✅ Success, Error, Warning, etc. | ❌ Manual styling |
| Stack management | ✅ Visible count control | N/A |
| Alignment | ✅ Top or Bottom | |
| Use case | Non-critical notifications | Actions with undo |
Use DhyānToast when:
- You need to show multiple notifications simultaneously
- You want category-based styling (success, error, warning)
- You need gesture-based interactions
- You want notifications at the top of the screen
Use Snackbar when:
- You need a single, action-oriented message
- You want to provide an "Undo" action
- You prefer Material Design's standard bottom placement
- You need integration with Material3's standard components
showToast()- Show a new toast notificationclearAll()- Clear all active toasts- Similar to
SnackbarHostStatefrom Material3
- Main composable for displaying toasts
- Configurable alignment, auto-dismiss, theming
- Support for custom toast UI
- Drop-in replacement for Material3 Scaffold
- Adds
toastHostparameter while maintaining all Scaffold features - Works with
topBar,bottomBar,snackbarHost,floatingActionButton, etc.
ToastCategory.Success- Success notificationsToastCategory.Error- Error messagesToastCategory.Warning- Warning alertsToastCategory.General- General informationToastCategory.Custom(name)- Custom categories
ToastAlignment.Top- Show toasts at top of screenToastAlignment.Bottom- Show toasts at bottom of screen
"Dhyān" (ध्यान) means "attention" or "focus" in Sanskrit. This library is designed to grab user attention elegantly with:
- Non-intrusive - Toasts appear smoothly without blocking content
- Stackable - Multiple notifications without overwhelming the UI
- Dismissable - Easy gesture controls for user convenience
- Themed - Category-based styling for instant recognition
- Accessible - Clear visual hierarchy and readable text
- Use
visibleCountto limit visible toasts and maintain performance - Clear toasts when navigating away:
toastHostState.clearAll() - Use appropriate
autoDismissDelayto avoid overwhelming users
- Success: Use for completed actions (save, upload, sync)
- Error: Use for failures that need attention (network errors, validation)
- Warning: Use for potential issues (low storage, deprecated features)
- General: Use for informational messages (tips, updates)
- Keep messages concise and scannable
- Use titles for additional context
- Icons help with quick visual identification
- Auto-dismiss gives users time to read
- Tap to pause allows users to read at their own pace
// Good - Clear and actionable
toastHostState.showToast(
title = "File saved",
message = "Document.pdf saved successfully",
category = ToastCategory.Success
)
// Avoid - Too verbose
toastHostState.showToast(
title = "Success",
message = "The file that you have been working on has been successfully saved to your device storage",
category = ToastCategory.Success
)Contributions are welcome! Please feel free to submit a Pull Request.
Support it by joining stargazers for this repository. ⭐ Also, follow me on GitHub for more cool projects!
Copyright 2025 AndroidPoet (Ranbir Singh)
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.