Elegant, glassy, capsule‑shaped bottom navigation for Kotlin Multiplatform (Android + iOS) built with Compose Multiplatform.
- Multiplatform: Android and iOS targets from one codebase
- Capsule Aesthetic: Uses
ContinuousCapsuleshape fromKMP‑Capsulefor a crisp, modern look - Glass Effect: Optional translucent “liquid glass” background
- Haptics: Platform‑specific haptic feedback on selection
- Safe Area Aware: Respects iOS home indicator and Android nav bars
- Tiny API: Simple
NavigationItem+NavigationConfigwith sane defaults
Repository: lamplis/KMP-Capsule-Navigation-Menu
GitHub: https://github.com/lamplis/KMP-Capsule-Navigation-Menu.git
- Add the module to your Gradle settings
// settings.gradle.kts (root)
include(":libs:KMP-Capsule-Navigation-Menu")
project(":libs:KMP-Capsule-Navigation-Menu").projectDir = File(rootDir, "libs/KMP-Capsule-Navigation-Menu")- Depend on it from your shared/app module
// composeApp/build.gradle.kts (example)
commonMain.dependencies {
implementation(project(":libs:KMP-Capsule-Navigation-Menu"))
implementation(project(":libs:KMP-Capsule")) // ContinuousCapsule dependency
}- Use in your Composable
@Composable
fun MyBottomBar(selectedIndex: Int, onSelect: (Int) -> Unit, modifier: Modifier = Modifier) {
val items = listOf(
NavigationItem("Home", Icons.Default.Home, "home"),
NavigationItem("Collection", Icons.Default.AccountCircle, "collection", badge = "3"),
NavigationItem("Trade", Icons.Default.SwapHoriz, "trade"),
NavigationItem("Nearby", Icons.Default.LocationOn, "nearby")
)
FloatingBottomNavigation(
selectedIndex = selectedIndex,
onItemSelected = onSelect,
items = items,
config = NavigationConfig(),
modifier = modifier
)
}data class NavigationItem(
val title: String,
val icon: ImageVector,
val route: String,
val badge: String? = null
)
data class NavigationConfig(
val backgroundColor: Color = Color.Unspecified,
val selectedItemColor: Color = Color.Unspecified,
val unselectedItemColor: Color = Color.Unspecified,
val height: Dp = 72.dp,
val horizontalPadding: Dp = 32.dp,
val verticalPadding: Dp = 12.dp,
val itemSpacing: Dp = 8.dp,
val animationDuration: Int = 300,
val enableHapticFeedback: Boolean = true,
val enableGlassEffect: Boolean = true,
val glassEffectAlpha: Float = 0.92f
)
@Composable
fun FloatingBottomNavigation(
selectedIndex: Int,
onItemSelected: (Int) -> Unit,
items: List<NavigationItem>,
config: NavigationConfig = NavigationConfig(),
modifier: Modifier = Modifier
)- Colors default to your
MaterialThemewhenColor.Unspecifiedis used. - Capsule shape is provided by
ContinuousCapsulefrom theKMP‑Capsulelibrary. - Haptics are implemented per-platform (Android/iOS) out of the box.
- The component pads itself using
WindowInsets.safeDrawingfor bottom/home indicators.
The library includes a hard‑coded preview (FloatingBottomNavigationPreview) under commonMain so Android Studio can render it. For Android Previews, the module applies compose.uiTooling.
@Composable
@Preview
fun FloatingBottomNavigationPreview() {
MaterialTheme {
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.primary) {
Box(Modifier.fillMaxSize()) {
var selected by remember { mutableStateOf(0) }
val items = listOf(
NavigationItem("Home", Icons.Filled.Home, "home"),
NavigationItem("Collection", Icons.Filled.AccountCircle, "collection", badge = "3"),
NavigationItem("Trade", Icons.Filled.SwapHoriz, "trade"),
NavigationItem("Nearby", Icons.Filled.LocationOn, "nearby")
)
FloatingBottomNavigation(
selectedIndex = selected,
onItemSelected = { selected = it },
items = items,
modifier = Modifier.align(Alignment.BottomCenter).fillMaxWidth()
)
}
}
}
}- Set
backgroundColor,selectedItemColor,unselectedItemColorinNavigationConfig, or leave asColor.Unspecifiedto useMaterialTheme. - Enable/disable the glass effect with
enableGlassEffectand tuneglassEffectAlpha(0.0 – 1.0). - Adjust
height, paddings anditemSpacingto fit your layout.
- Android: Haptic feedback uses
View.performHapticFeedback. - iOS: Haptics use
UIImpactFeedbackGenerator. - Both platforms respect safe areas/home indicators via
WindowInsets.safeDrawing.
Build module only:
./gradlew :libs:KMP-Capsule-Navigation-Menu:buildUse from a sample app (Android):
./gradlew :composeApp:assembleDebug- Badges with counts + animations
- Optional labels on selection only
- Accessibility refinements and TalkBack/VoiceOver docs
This project is licensed under the MIT License – see LICENSE.
For updates and issues, see the GitHub repository:
lamplis/KMP-Capsule-Navigation-Menu — https://github.com/lamplis/KMP-Capsule-Navigation-Menu.git
