SkillAgentSearch skills...

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/SnapNotify

README

SnapNotify

Android Weekly Kotlin Compose Android License Maven Central Tests Coverage

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 Demo

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 SnackbarHostState management
  • Passing CoroutineScope everywhere
  • 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)

  1. Bump the library version in snapnotify/build.gradle.kts (mavenPublishing { coordinates(...) }), demo versionCode / versionName, CHANGELOG.md, and the installation/coordinates snippets in this README.
  2. Run ./gradlew check.
  3. Commit, create an annotated tag vX.Y.Z, and push the branch and tag to GitHub.
  4. Publish to Maven Central: ./gradlew :snapnotify:publishAndReleaseToMavenCentral with Central Portal credentials and signing (see comments in gradle.properties).
  5. 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 SnapNotifyProvider at any level of your app hierarchy
  • App-wide, screen-specific, or feature-scoped snackbars
  • No SnackbarHostState or CoroutineScope management needed

βœ… Thread-Safe

  • Call from ViewModels and Composables safely
  • Background thread support with proper synchronization
  • No more IllegalStateException crashes

βœ… 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.1k

The 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.1k

The 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>

View on GitHub
GitHub Stars34
CategoryDesign
Updated1d ago
Forks3

Languages

Kotlin

Security Score

80/100

Audited on Apr 5, 2026

No findings