Charts
Chartsanimated
Box plot
A box-and-whisker plot of quartiles and medians that wipes in across categories.
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 BoxStat(val min: Float, val q1: Float, val med: Float, val q3: Float, val max: Float)
@Composable
fun BoxPlot(
boxes: List<BoxStat> = listOf(
BoxStat(0.2f, 0.35f, 0.5f, 0.65f, 0.85f),
BoxStat(0.3f, 0.45f, 0.55f, 0.7f, 0.9f),
BoxStat(0.15f, 0.3f, 0.42f, 0.55f, 0.75f),
BoxStat(0.35f, 0.5f, 0.62f, 0.78f, 0.95f),
),
accent: Color = Color(0xFF6366F1),
modifier: Modifier = Modifier,
) {
val reveal = remember { Animatable(0f) }
LaunchedEffect(Unit) { reveal.animateTo(1f, tween(900, easing = EaseOutCubic)) }
Canvas(modifier.fillMaxWidth().height(130.dp)) {
val slot = size.width / boxes.size
val bw = slot * 0.46f
fun y(v: Float) = size.height * (1f - v)
clipRect(right = size.width * reveal.value) {
boxes.forEachIndexed { i, b ->
val cx = i * slot + slot / 2
drawLine(accent, Offset(cx, y(b.max)), Offset(cx, y(b.min)), 1.5.dp.toPx())
drawLine(accent, Offset(cx - bw / 3, y(b.max)), Offset(cx + bw / 3, y(b.max)), 1.5.dp.toPx())
drawLine(accent, Offset(cx - bw / 3, y(b.min)), Offset(cx + bw / 3, y(b.min)), 1.5.dp.toPx())
val top = y(b.q3)
val h = y(b.q1) - top
drawRoundRect(accent.copy(alpha = 0.22f), Offset(cx - bw / 2, top), Size(bw, h), CornerRadius(3.dp.toPx()))
drawRoundRect(accent, Offset(cx - bw / 2, top), Size(bw, h), CornerRadius(3.dp.toPx()), style = Stroke(1.5.dp.toPx()))
drawLine(accent, Offset(cx - bw / 2, y(b.med)), Offset(cx + bw / 2, y(b.med)), 2.dp.toPx())
}
}
}
}