Docs / Bottom bars / 21
BuoyBottomBar
Floating pill whose selected icon lifts over its label, with a buoy in the bottom edge that dives and resurfaces under the next tab.
Preview


A floating pill of icon-only tabs. The selected icon fills in and lifts over its label, with a small buoy floating half-sunk in the bottom edge underneath. On a new selection the buoy dives below the edge, travels across and bobs back up under the new tab.
Usage
BuoyBarItem has no center item: any tab can be selected, and every slot gets the same width. The bar only shows icons until a tab is selected; the selected one switches to its selectedIcon, lifts it and shows its label underneath. The rest of the time label is read out by TalkBack.
import com.nameisjayant.bottombar.buoy.BuoyBarItem
import com.nameisjayant.bottombar.buoy.BuoyBottomBar
import com.nameisjayant.bottombar.buoy.BuoyBottomBarDefaultsval items = listOf(
BuoyBarItem("Home", Icons.Outlined.Home, Icons.Filled.Home),
BuoyBarItem("Wallet", Icons.Outlined.AccountBalanceWallet, Icons.Filled.AccountBalanceWallet),
BuoyBarItem("Analysis", Icons.Outlined.PieChart, Icons.Filled.PieChart),
BuoyBarItem("Profile", Icons.Outlined.Person, Icons.Filled.Person),
)
BuoyBottomBar(
items = items,
selectedIndex = selectedIndex,
onItemClick = { selectedIndex = it },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
)Sizing and behavior
The bar is a BarHeight (64dp) tall pill and has no outer margin of its own, so pass one through modifier. The BuoySize (10dp) buoy rests centered on the bottom edge, so only its top half shows. When the selection changes it dives up to DiveDepth (8dp) below its resting spot, deep enough to disappear, and resurfaces under the new tab. The outline is convex, so shadowElevation works on every API level.
Colors
Colors come from BuoyBottomBarDefaults.colors(darkTheme), lightColors(...) and darkColors(...). Start from either palette and override only what you need.
| Color | Used for |
|---|---|
containerColor | The bar |
selectedContentColor | Icon and label of the selected tab |
unselectedContentColor | Icons of the other tabs |
buoyColor | The buoy (defaults to selectedContentColor) |
BuoyBottomBar(
items = items,
selectedIndex = selectedIndex,
onItemClick = { selectedIndex = it },
// Follow your app's theme instead of the system one.
colors = BuoyBottomBarDefaults.colors(darkTheme = isDarkTheme),
)API
The full signature of the composable and its item class:
fun BuoyBottomBar(
items: List<BuoyBarItem>,
selectedIndex: Int,
onItemClick: (index: Int) -> Unit,
modifier: Modifier = Modifier,
colors: BuoyBottomBarColors = BuoyBottomBarDefaults.colors(),
labelStyle: TextStyle = BuoyBottomBarDefaults.LabelStyle,
shadowElevation: Dp = 0.dp,
windowInsets: WindowInsets = BuoyBottomBarDefaults.windowInsets,
)
class BuoyBarItem(
val label: String,
val icon: ImageVector,
val selectedIcon: ImageVector = icon,
)