Navigation
Navigationanimated

Floating pill bar

A floating rounded bar where the active item expands into a labelled pill.

Home

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 FloatingPillBar() {
    var selected by remember { mutableStateOf(0) }
    val items = listOf(
        Icons.Filled.Home to "Home",
        Icons.Filled.Search to "Search",
        Icons.Filled.FavoriteBorder to "Saved",
        Icons.Filled.Person to "Me",
    )
    Surface(shape = CircleShape, tonalElevation = 3.dp, shadowElevation = 6.dp) {
        Row(
            Modifier.padding(6.dp),
            horizontalArrangement = Arrangement.spacedBy(4.dp),
        ) {
            items.forEachIndexed { i, (icon, label) ->
                val on = i == selected
                Surface(
                    onClick = { selected = i },
                    shape = CircleShape,
                    color = if (on) MaterialTheme.colorScheme.primary
                        else Color.Transparent,
                    contentColor = if (on) MaterialTheme.colorScheme.onPrimary
                        else MaterialTheme.colorScheme.onSurfaceVariant,
                ) {
                    Row(
                        Modifier.padding(horizontal = 14.dp, vertical = 10.dp),
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        Icon(icon, null, Modifier.size(20.dp))
                        AnimatedVisibility(on) {
                            Text(label, Modifier.padding(start = 6.dp),
                                style = MaterialTheme.typography.labelMedium)
                        }
                    }
                }
            }
        }
    }
}