Blocks
Spending Statistic
A dark analytics screen with month tabs, a smooth spending line chart with a peak marker and category cards.
9:41
Statistic
▦DecemberJanuaryFebruaryMar
Subscription & Phone
Average level
$ 452
11
Mon
12
Tue
13
Wed
14
Thu
15
Fri
16
Sat
Spending categories
Subscription & Phone
Housing & energy
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
@Composable
fun SpendingStatisticScreen(months: List<String>, points: List<Float>) {
val accent = Color(0xFF3B82F6)
Column(Modifier.fillMaxSize().background(Color(0xFF0B1020)).padding(16.dp)) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, null, tint = Color.White)
Text("Statistic", color = Color.White, fontWeight = FontWeight.Bold)
Icon(Icons.Filled.GridView, null, tint = Color.White)
}
ScrollableTabRow(selectedTabIndex = 1, edgePadding = 0.dp,
containerColor = Color.Transparent, contentColor = Color.White,
modifier = Modifier.padding(top = 12.dp)) {
months.forEachIndexed { i, m ->
Tab(selected = i == 1, onClick = {}, text = { Text(m) })
}
}
Text("Subscription & Phone", Modifier.padding(top = 16.dp),
color = Color.White.copy(alpha = 0.6f), style = MaterialTheme.typography.bodySmall)
Canvas(Modifier.fillMaxWidth().height(120.dp).padding(top = 12.dp)) {
val path = Path()
val stepX = size.width / (points.size - 1)
points.forEachIndexed { i, p ->
val x = i * stepX
val y = size.height * (1 - p)
if (i == 0) path.moveTo(x, y) else path.lineTo(x, y)
}
drawPath(path, color = accent, style = Stroke(width = 3f, cap = StrokeCap.Round))
}
Text("Spending categories", Modifier.padding(top = 16.dp),
color = Color.White, style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold)
Row(Modifier.padding(top = 12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp)) {
listOf(
Icons.Filled.Phone to "Subscription & Phone",
Icons.Filled.Home to "Housing & energy",
).forEach { (icon, label) ->
Surface(color = Color.White.copy(alpha = 0.05f), shape = RoundedCornerShape(16.dp),
modifier = Modifier.weight(1f)) {
Column(Modifier.padding(12.dp)) {
Surface(color = Color.White.copy(alpha = 0.1f), shape = CircleShape,
modifier = Modifier.size(36.dp)) {
Box(contentAlignment = Alignment.Center) {
Icon(icon, null, tint = Color(0xFF93C5FD))
}
}
Text(label, Modifier.padding(top = 8.dp), color = Color.White,
style = MaterialTheme.typography.labelMedium)
}
}
}
}
}
}