Disclosures
Disclosuresanimated

Tree view

A nested file tree whose folders rotate open to reveal indented children.

components

button.kt

card.kt

avatar.kt

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 TreeNode(label: String, children: List<String>) {
    var open by remember { mutableStateOf(true) }
    val rotation by animateFloatAsState(if (open) 90f else 0f, label = "tw")
    Column {
        Row(
            Modifier.fillMaxWidth().clickable { open = !open }.padding(vertical = 6.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Icon(
                Icons.Filled.ChevronRight, null,
                Modifier.size(16.dp).rotate(rotation),
                tint = MaterialTheme.colorScheme.onSurfaceVariant,
            )
            Spacer(Modifier.width(4.dp))
            Icon(Icons.Filled.Folder, null, Modifier.size(16.dp),
                tint = Color(0xFF3B82F6))
            Spacer(Modifier.width(6.dp))
            Text(label, style = MaterialTheme.typography.bodyMedium)
        }
        AnimatedVisibility(open) {
            Column(Modifier.padding(start = 26.dp)) {
                children.forEach { c ->
                    Row(Modifier.padding(vertical = 5.dp),
                        verticalAlignment = Alignment.CenterVertically) {
                        Icon(Icons.AutoMirrored.Filled.InsertDriveFile, null,
                            Modifier.size(14.dp),
                            tint = MaterialTheme.colorScheme.onSurfaceVariant)
                        Spacer(Modifier.width(6.dp))
                        Text(c, style = MaterialTheme.typography.bodySmall)
                    }
                }
            }
        }
    }
}