SnapNotify
π A lightweight, thread-safe Snackbar library for Jetpack Compose with zero-ceremony setup. Show snackbars from anywhere with beautiful theming, queue management, and optional Hilt integration. 100% Kotlin.
Install / Use
/learn @iVamsi/SnapNotifyREADME
SnapNotify
A drop-in Snackbar solution for Jetpack Compose that brings back the simplicity of the View system while leveraging modern Compose patterns.
π¬ Demo
<div align="center">
SnapNotify in action: Simple messages, themed styling, custom designs, and queue management
</div>π The Problem
Jetpack Compose's built-in Snackbar system requires significant boilerplate:
- Manual
SnackbarHostStatemanagement - Passing
CoroutineScopeeverywhere - Complex setup in every screen
- Thread-safety concerns when calling from background threads
- Cumbersome queue management for multiple messages
// Traditional Compose approach - lots of boilerplate π
@Composable
fun MyScreen() {
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) }
) {
// Your content
Button(
onClick = {
scope.launch {
snackbarHostState.showSnackbar("Message")
}
}
) {
Text("Show Snackbar")
}
}
}
β¨ The Solution
SnapNotify eliminates all the boilerplate with a clean, thread-safe API:
// SnapNotify approach - zero ceremony! π
@Composable
fun MyScreen() {
Button(
onClick = { SnapNotify.show("Message") }
) {
Text("Show Snackbar")
}
}
π Installation
Add to your build.gradle.kts:
dependencies {
implementation("io.github.ivamsi:snapnotify:1.0.6")
}
Hilt Integration (Optional): SnapNotify works with or without Hilt! If you use Hilt, no additional setup needed.
Changelog
Release history is in CHANGELOG.md.
Developing
This repositoryβs sample app depends on project(":snapnotify") so ./gradlew check works on a clean clone without publishing. To validate the same artifact consumers get from Maven, run ./gradlew :snapnotify:publishToMavenLocal and point a module to io.github.ivamsi:snapnotify:1.0.6 with mavenLocal() in dependencyResolutionManagement (or your module repositories).
Releasing (maintainers)
- Bump the library version in
snapnotify/build.gradle.kts(mavenPublishing { coordinates(...) }), demoversionCode/versionName, CHANGELOG.md, and the installation/coordinates snippets in this README. - Run
./gradlew check. - Commit, create an annotated tag
vX.Y.Z, and push the branch and tag to GitHub. - Publish to Maven Central:
./gradlew :snapnotify:publishAndReleaseToMavenCentralwith Central Portal credentials and signing (see comments ingradle.properties). - On GitHub, create a Release from that tag and attach release notes (can mirror the changelog section).
π― Quick Start
1. Setup (Flexible Usage)
Wrap your content with SnapNotifyProvider where you want snackbar functionality:
App-wide snackbars:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SnapNotifyProvider {
MyAppContent() // Entire app has snackbar access
}
}
}
}
Screen-specific snackbars:
@Composable
fun MyScreen() {
SnapNotifyProvider {
// Only this screen and its children can show snackbars
ScreenContent()
}
}
Feature-scoped snackbars:
@Composable
fun ShoppingCart() {
Card {
SnapNotifyProvider {
// Snackbars appear within this card's bounds
CartItems()
AddToCartButton()
}
}
}
Custom styled snackbars:
@Composable
fun MyScreen() {
SnapNotifyProvider(
style = SnackbarStyle.error() // Pre-built error styling
) {
ScreenContent()
}
}
2. Usage (Anywhere in your app)
// Simple message
SnapNotify.show("Operation completed successfully!")
// With action button
SnapNotify.show("Error occurred", "Retry") {
retryOperation()
}
// With custom duration
SnapNotify.show("Long message", duration = SnackbarDuration.Long)
// With custom duration in milliseconds
SnapNotify.show("7 second message", durationMillis = 7000)
// Clear all pending messages
SnapNotify.clearAll()
// Themed styling methods
SnapNotify.showSuccess("Operation completed!")
SnapNotify.showError("Something went wrong!")
SnapNotify.showWarning("Please check your input!")
SnapNotify.showInfo("Here's some information!")
// Themed methods with actions
SnapNotify.showSuccess("File saved!", "View") { openFile() }
SnapNotify.showError("Upload failed", "Retry") { retryUpload() }
// Themed methods with custom duration
SnapNotify.showError("Network timeout", "Retry", { retry() }, durationMillis = 8000)
SnapNotify.showSuccess("Quick success!", durationMillis = 2000)
// Custom styling for specific messages
val customStyle = SnackbarStyle(
containerColor = Color(0xFF6A1B9A),
contentColor = Color.White,
actionColor = Color(0xFFE1BEE7)
)
SnapNotify.showStyled("Custom styled message!", customStyle)
SnapNotify.showStyled("10 second custom style", customStyle, durationMillis = 10000)
π Key Features
π Latest Updates (v1.0.6)
- Toolchain: Android Gradle Plugin 9.1 / Gradle 9.3.1, Kotlin 2.3.20 with built-in Kotlin in AGP 9, updated AndroidX / Compose BOM / Hilt
- Queue Configuration: Configure max queue size and get notified when messages are dropped
- Enhanced Keyboard Handling: Snackbars now automatically avoid IME (keyboard) and work with navigation bars
- Provider Flexibility: New parameters for alignment, insets, and custom host rendering
- Architecture Improvements: Non-blocking mutex, proper dispatcher management, optimized style reuse
- Custom Duration Support: Precise millisecond timing control for all methods
- Expanded Test Coverage: 74+ tests with 100% public API coverage
β Flexible Setup
- Use
SnapNotifyProviderat any level of your app hierarchy - App-wide, screen-specific, or feature-scoped snackbars
- No
SnackbarHostStateorCoroutineScopemanagement needed
β Thread-Safe
- Call from ViewModels and Composables safely
- Background thread support with proper synchronization
- No more
IllegalStateExceptioncrashes
β Smart Queue Management
- Handles multiple rapid Snackbar triggers gracefully
- No overlapping or lost messages
- Singleton architecture prevents duplicate displays
β Lifecycle-Aware
- Survives configuration changes
- Prevents memory leaks
- Automatic provider deduplication
β Action Support
- Optional action buttons with callbacks
- Seamless integration with your business logic
β Comprehensive Styling
- Pre-built themes: Success, Error, Warning, Info with semantic colors
- Themed methods:
showSuccess(),showError(),showWarning(),showInfo() - Custom styling:
showStyled()for per-message customization - Full customization: Colors, shapes, elevation, typography
- Provider-level defaults: Set default styles for entire sections
- Material3 integration: Seamless with your app's design system
π Detailed Usage
Basic Messages
// Simple text message
SnapNotify.show("Profile updated successfully!")
// Different durations
SnapNotify.show("Quick message", duration = SnackbarDuration.Short)
SnapNotify.show("Important info", duration = SnackbarDuration.Long)
SnapNotify.show("Persistent message", duration = SnackbarDuration.Indefinite)
// Custom durations in milliseconds
SnapNotify.show("2 second message", durationMillis = 2000)
SnapNotify.show("30 second timeout", durationMillis = 30000)
Action Buttons
// With action callback
SnapNotify.show("Message deleted", "Undo") {
undoDelete()
}
// Error handling with retry
SnapNotify.show("Network error", "Retry") {
viewModel.retryNetworkCall()
}
// Clear pending messages when navigating or context changes
SnapNotify.clearAll()
β±οΈ Custom Duration Control
Precise timing control with millisecond accuracy:
// Quick notifications (1-3 seconds)
SnapNotify.show("Quick toast", durationMillis = 1500)
SnapNotify.showSuccess("Saved!", durationMillis = 2000)
// Standard notifications (4-8 seconds)
SnapNotify.show("Processing complete", durationMillis = 5000)
SnapNotify.showInfo("New feature available", durationMillis = 6000)
// Long notifications (10+ seconds)
SnapNotify.showError("Network error - retrying in 15s", "Retry Now", {
retryNetworkCall()
}, durationMillis = 15000)
// Custom styled with timing
val urgentStyle = SnackbarStyle(
containerColor = Color.Red,
contentColor = Color.White
)
SnapNotify.showStyled("Critical alert!", urgentStyle, durationMillis = 12000)
// With action buttons - users can still interact b
Related Skills
clearshot
Structured screenshot analysis for UI implementation and critique. Analyzes every UI screenshot with a 5Γ5 spatial grid, full element inventory, and design system extraction β facts and taste together, every time. Escalates to full implementation blueprint when building. Trigger on any digital interface image file (png, jpg, gif, webp β websites, apps, dashboards, mockups, wireframes) or commands like 'analyse this screenshot,' 'rebuild this,' 'match this design,' 'clone this.' Skip for non-UI images (photos, memes, charts) unless the user explicitly wants to build a UI from them. Does NOT trigger on HTML source code, CSS, SVGs, or any code pasted as text.
openpencil
2.1kThe world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
openpencil
2.1kThe world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
ui-ux-designer
Use this agent when you need to design, implement, or improve user interface components and user experience flows. Examples include: creating new pages or components, improving existing UI layouts, implementing responsive designs, optimizing user interactions, building forms or dashboards, analyzing existing UI through browser snapshots, or when you need to ensure UI components follow design system standards and shadcn/ui best practices.\n\n<example>\nContext: User needs to create a new dashboard page for team management.\nuser: "I need to create a team management dashboard where users can view team members, invite new members, and manage roles"\nassistant: "I'll use the ui-ux-designer agent to design and implement this dashboard with proper UX considerations, using shadcn/ui components and our design system tokens."\n</example>\n\n<example>\nContext: User wants to improve the user experience of an existing form.\nuser: "The signup form feels clunky and users are dropping off. Can you improve it?"\nassistant: "Let me use the ui-ux-designer agent to analyze the current form UX and implement improvements using our design system and shadcn/ui components."\n</example>\n\n<example>\nContext: User wants to evaluate and improve existing UI.\nuser: "Can you take a look at our pricing page and see how we can make it more appealing and user-friendly?"\nassistant: "I'll use the ui-ux-designer agent to take a snapshot of the current pricing page, analyze the UX against Notion-inspired design principles, and implement improvements using our design tokens."\n</example>
