Charts
Chartsanimated

Violin

A violin plot of mirrored density curves that bloom open from their center axes.

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 ViolinPlot(
    densities: List<List<Float>> = listOf(
        listOf(0.1f, 0.3f, 0.7f, 1f, 0.6f, 0.25f, 0.08f),
        listOf(0.08f, 0.2f, 0.5f, 0.9f, 1f, 0.4f, 0.12f),
        listOf(0.12f, 0.4f, 0.9f, 0.7f, 0.5f, 0.3f, 0.1f),
    ),
    accent: Color = Color(0xFFA855F7),
    modifier: Modifier = Modifier,
) {
    val open by animateFloatAsState(1f, tween(900, easing = EaseOutBack), label = "o")
    Canvas(modifier.fillMaxWidth().height(130.dp)) {
        val slot = size.width / densities.size
        val maxW = slot * 0.42f
        densities.forEachIndexed { i, d ->
            val cx = i * slot + slot / 2
            val stepY = size.height / (d.size - 1)
            val path = Path()
            d.forEachIndexed { j, v ->
                val x = cx + maxW * v * open
                val y = j * stepY
                if (j == 0) path.moveTo(x, y) else path.lineTo(x, y)
            }
            for (j in d.indices.reversed()) {
                path.lineTo(cx - maxW * d[j] * open, j * stepY)
            }
            path.close()
            drawPath(path, accent.copy(alpha = 0.7f))
        }
    }
}