Blocks

Notifications Center

A grouped notifications inbox with an info banner, colored category avatars and per-section mark-as-read.

9:41

Notifications

Information!

Please note that there might be a brief delay in securing your seats at the theater while processing your ticket purchase.

Today

Mark all read
🎬

50% Off Extravaganza! Grab Your Movie Tickets at Half the Price!

10:00 AM

🍄

Successful purchase enjoy unforgettable Adventures with Super Mario movies

10:50 AM

⚠️

Yo, Your account got spotted on a new device

11:25 AM

Yesterday

Mark all read
🎬

Jingle Deals: Spectacular Christmas Discounts at the Bioskop!

10:00 AM

🎬

Presale Frenzy: Grab Your Tickets Now at a Whopping 90% Discount!

10:00 AM

Installation

caveui components are copy-paste Jetpack Compose built entirely on Material 3 — there's no caveui dependency to add. Make sure Material 3 is on your classpath (it ships with the Compose BOM), then copy the Usage snippet below into your project.

kotlin
// build.gradle.kts (module)
dependencies {
    implementation(platform("androidx.compose:compose-bom:2025.06.00"))
    implementation("androidx.compose.material3:material3")
}

Usage

kotlin
data class Notif(val emoji: String, val title: String, val time: String, val tint: Color)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NotificationsScreen(today: List<Notif>, onBack: () -> Unit) {
    val red = Color(0xFFEF4444)
    Scaffold(topBar = {
        TopAppBar(
            title = { Text("Notifications", fontWeight = FontWeight.Bold) },
            navigationIcon = {
                IconButton(onClick = onBack) {
                    Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back")
                }
            },
            actions = { IconButton(onClick = {}) { Icon(Icons.Filled.Settings, null) } },
        )
    }) { padding ->
        Column(Modifier.fillMaxSize().padding(padding)) {
            Surface(color = red.copy(alpha = 0.1f), shape = RoundedCornerShape(16.dp),
                modifier = Modifier.padding(16.dp).fillMaxWidth()) {
                Column(Modifier.padding(12.dp)) {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        Icon(Icons.Filled.Notifications, null, tint = red,
                            modifier = Modifier.size(18.dp))
                        Spacer(Modifier.width(6.dp))
                        Text("Information!", color = red, fontWeight = FontWeight.Bold,
                            style = MaterialTheme.typography.labelMedium)
                    }
                    Text("There might be a brief delay while processing your ticket purchase.",
                        color = red.copy(alpha = 0.9f),
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.padding(top = 6.dp))
                }
            }
            Row(Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                horizontalArrangement = Arrangement.SpaceBetween) {
                Text("Today", fontWeight = FontWeight.SemiBold)
                Text("Mark all read", color = red, style = MaterialTheme.typography.labelMedium)
            }
            today.forEach { n ->
                ListItem(
                    leadingContent = {
                        Surface(color = n.tint, shape = CircleShape,
                            modifier = Modifier.size(36.dp)) {
                            Box(contentAlignment = Alignment.Center) { Text(n.emoji) }
                        }
                    },
                    headlineContent = { Text(n.title, style = MaterialTheme.typography.bodySmall) },
                    supportingContent = { Text(n.time) },
                )
            }
        }
    }
}