Blocks

Finance Dashboard

A personal-finance home screen with a teal balance card, quick-action row and live transaction list.

LE

Good Morning,

Lucia Esperanza

Available Balance

$ 817,432.09

Scan
Transfer
Topup
Partner
Promo

Transaction history

View all
OD

Octavia Devi

12 Des, 10:32 AM

-$15.89
AA

Aditya Anugrah

7 Des, 03:08 PM

+$129.21
ML

Melasari

5 Des, 12:12 AM

-$15.89
JW

Judha Wijaya

18 Des, 08:24 AM

+$89.73

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 Transaction(
    val name: String,
    val date: String,
    val amount: String,
    val positive: Boolean,
)

@Composable
fun FinanceDashboardScreen(
    userName: String,
    balance: String,
    transactions: List<Transaction>,
    onWithdraw: () -> Unit,
    onHistory: () -> Unit,
) {
    val teal = Color(0xFF3EADA0)
    val tealDark = Color(0xFF1A3A38)
    val actions = listOf("Scan", "Transfer", "Topup", "Partner", "Promo")

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color(0xFFF0F5F4))
            .verticalScroll(rememberScrollState()),
    ) {
        // Header
        Row(
            modifier = Modifier.fillMaxWidth().padding(20.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Surface(
                shape = CircleShape,
                color = teal.copy(alpha = 0.3f),
                modifier = Modifier.size(40.dp),
            ) {}
            Spacer(Modifier.width(12.dp))
            Column(Modifier.weight(1f)) {
                Text(
                    "Good Morning,",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
                Text(userName, style = MaterialTheme.typography.titleSmall)
            }
            IconButton(onClick = {}) {
                Icon(Icons.Outlined.Notifications, "Notifications")
            }
        }

        // Balance card
        Box(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .fillMaxWidth()
                .clip(RoundedCornerShape(24.dp))
                .background(
                    Brush.linearGradient(
                        listOf(Color(0xFF5AC8BE), Color(0xFF3EADA0), Color(0xFF2A7D74)),
                    ),
                )
                .padding(20.dp),
        ) {
            Column {
                Row(
                    Modifier.fillMaxWidth(),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Text(
                        "Available Balance",
                        color = Color.White.copy(alpha = 0.8f),
                        style = MaterialTheme.typography.labelMedium,
                    )
                    Spacer(Modifier.width(4.dp))
                    Icon(
                        Icons.Outlined.Visibility,
                        contentDescription = "Show balance",
                        tint = Color.White.copy(alpha = 0.8f),
                        modifier = Modifier.size(16.dp),
                    )
                    Spacer(Modifier.weight(1f))
                    Surface(
                        color = Color.White.copy(alpha = 0.2f),
                        shape = CircleShape,
                    ) {
                        Text(
                            "🇺🇸 US Dollar",
                            modifier = Modifier.padding(
                                horizontal = 10.dp, vertical = 4.dp
                            ),
                            color = Color.White,
                            style = MaterialTheme.typography.labelSmall,
                        )
                    }
                }
                Spacer(Modifier.height(12.dp))
                Text(
                    "$ $balance",
                    color = Color.White,
                    style = MaterialTheme.typography.headlineLarge,
                    fontWeight = FontWeight.ExtraBold,
                )
                Spacer(Modifier.height(16.dp))
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    Button(
                        onClick = onWithdraw,
                        colors = ButtonDefaults.buttonColors(
                            containerColor = tealDark,
                        ),
                        shape = CircleShape,
                        contentPadding = PaddingValues(
                            horizontal = 16.dp, vertical = 8.dp
                        ),
                    ) {
                        Icon(
                            Icons.Filled.CallMade,
                            contentDescription = null,
                            modifier = Modifier.size(16.dp),
                        )
                        Spacer(Modifier.width(4.dp))
                        Text("Withdraw")
                    }
                    OutlinedButton(
                        onClick = onHistory,
                        shape = CircleShape,
                        colors = ButtonDefaults.outlinedButtonColors(
                            containerColor = Color.White.copy(alpha = 0.9f),
                        ),
                        border = BorderStroke(0.dp, Color.Transparent),
                        contentPadding = PaddingValues(
                            horizontal = 16.dp, vertical = 8.dp
                        ),
                    ) {
                        Icon(
                            Icons.Outlined.History,
                            contentDescription = null,
                            modifier = Modifier.size(16.dp),
                            tint = MaterialTheme.colorScheme.onSurface,
                        )
                        Spacer(Modifier.width(4.dp))
                        Text(
                            "History",
                            color = MaterialTheme.colorScheme.onSurface,
                        )
                    }
                }
            }
        }

        // Quick actions
        Card(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .padding(top = 12.dp)
                .fillMaxWidth(),
            shape = RoundedCornerShape(16.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface,
            ),
            elevation = CardDefaults.cardElevation(defaultElevation = 1.dp),
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 12.dp, vertical = 12.dp),
                horizontalArrangement = Arrangement.SpaceAround,
            ) {
                actions.forEachIndexed { i, label ->
                    Column(horizontalAlignment = Alignment.CenterHorizontally) {
                        Surface(
                            shape = CircleShape,
                            color = if (i == 1) tealDark
                                else MaterialTheme.colorScheme.surfaceVariant,
                            modifier = Modifier.size(44.dp),
                        ) {
                            Box(contentAlignment = Alignment.Center) {
                                Icon(
                                    when (i) {
                                        0 -> Icons.Outlined.QrCodeScanner
                                        1 -> Icons.Filled.SwapHoriz
                                        2 -> Icons.Filled.Add
                                        3 -> Icons.Outlined.Group
                                        else -> Icons.Outlined.Discount
                                    },
                                    contentDescription = label,
                                    modifier = Modifier.size(20.dp),
                                    tint = if (i == 1) Color.White
                                        else MaterialTheme.colorScheme.onSurfaceVariant,
                                )
                            }
                        }
                        Spacer(Modifier.height(4.dp))
                        Text(
                            label,
                            style = MaterialTheme.typography.labelSmall,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                }
            }
        }

        // Transaction history
        Card(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxWidth(),
            shape = RoundedCornerShape(24.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.surface,
            ),
            elevation = CardDefaults.cardElevation(defaultElevation = 1.dp),
        ) {
            Column(Modifier.padding(16.dp)) {
                Row(
                    Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Text(
                        "Transaction history",
                        style = MaterialTheme.typography.titleSmall,
                        fontWeight = FontWeight.ExtraBold,
                    )
                    TextButton(onClick = {}) {
                        Text(
                            "View all",
                            color = teal,
                            style = MaterialTheme.typography.labelMedium,
                        )
                    }
                }
                Spacer(Modifier.height(8.dp))
                transactions.forEach { tx ->
                    ListItem(
                        leadingContent = {
                            Surface(
                                shape = CircleShape,
                                color = teal.copy(alpha = 0.15f),
                                modifier = Modifier.size(40.dp),
                            ) {
                                Box(contentAlignment = Alignment.Center) {
                                    Text(
                                        tx.name.take(2).uppercase(),
                                        style = MaterialTheme.typography.labelSmall,
                                        fontWeight = FontWeight.Bold,
                                        color = teal,
                                    )
                                }
                            }
                        },
                        headlineContent = {
                            Text(
                                tx.name,
                                style = MaterialTheme.typography.bodyMedium,
                                fontWeight = FontWeight.SemiBold,
                            )
                        },
                        supportingContent = {
                            Text(
                                tx.date,
                                style = MaterialTheme.typography.labelSmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        },
                        trailingContent = {
                            Text(
                                tx.amount,
                                style = MaterialTheme.typography.bodyMedium,
                                fontWeight = FontWeight.Bold,
                                color = if (tx.positive) teal
                                    else Color(0xFFE53935),
                            )
                        },
                        colors = ListItemDefaults.colors(
                            containerColor = Color.Transparent,
                        ),
                    )
                }
            }
        }
    }
}