Docs / Bottom bars / 10

CrestBottomBar

Floating bar whose two wings climb towards a glowing orb resting in a socket between them.

  • Floating
  • Center orb
  • Icon + label

Preview

Light
Crest bottom bar in light theme, switching between tabs
Dark
Crest bottom bar in dark theme, switching between tabs

A floating bar split into two wings whose top edges climb towards the center, where a glowing orb rests in a round socket between them. Icons and labels always show; when the orb is selected it pops up out of the socket while the wings dip under it.

Usage

CrestBarItem follows the same rules as Valley: the middle item becomes the orb resting in the socket between the wings, so pass an odd number of items. Every side tab shows its icon and label; the selected one switches to its selectedIcon and takes selectedContentColor.

Imports
import com.nameisjayant.bottombar.crest.CrestBarItem
import com.nameisjayant.bottombar.crest.CrestBottomBar
import com.nameisjayant.bottombar.crest.CrestBottomBarDefaults
CrestBottomBar.kt
val items = listOf(
    CrestBarItem("Home", Icons.Outlined.Home, Icons.Filled.Home),
    CrestBarItem("Search", Icons.Outlined.Search, Icons.Filled.Search),
    CrestBarItem("Store", Icons.Outlined.Storefront, Icons.Filled.Storefront), // the orb
    CrestBarItem("Cart", Icons.Outlined.ShoppingCart, Icons.Filled.ShoppingCart),
    CrestBarItem("Profile", Icons.Outlined.Person, Icons.Filled.Person),
)

CrestBottomBar(
    items = items,
    selectedIndex = selectedIndex,
    onItemClick = { selectedIndex = it },
    // The bar floats, so keep it off the screen edges.
    modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
)

Sizing and behavior

The bar is BarHeight (68dp) tall at its outer ends, and each wing climbs WingRise (20dp) towards the center. The 54dp orb (OrbSize) rises OrbOverhang (6dp) above the point where the wings would meet, sits in a socket SocketGap (6dp) wider than itself, and casts a glow in its own color (OrbElevation). SocketShoulderRadius, TopCornerRadius and BottomCornerRadius round off the shape. When the orb is selected it pops up 8dp, so leave a little room above the bar. As with Valley, shadowElevation defaults to 0.dp and needs API 30+ because of the concave outline.

Colors

Colors come from CrestBottomBarDefaults.colors(darkTheme), lightColors(...) and darkColors(...). Start from either palette and override only what you need.

ColorUsed for
containerColorThe bar background
selectedContentColorIcon and label of the selected side tab
unselectedContentColorIcons of the other side tabs
unselectedLabelColorLabels of the other side tabs
orbColorFill of the center orb and its glow
orbContentColorIcon inside the orb
Theming
CrestBottomBar(
    items = items,
    selectedIndex = selectedIndex,
    onItemClick = { selectedIndex = it },
    // Follow your app's theme instead of the system one.
    colors = CrestBottomBarDefaults.colors(darkTheme = isDarkTheme),
)

API

The full signature of the composable and its item class:

com.nameisjayant.bottombar.crest
fun CrestBottomBar(
    items: List<CrestBarItem>,
    selectedIndex: Int,
    onItemClick: (index: Int) -> Unit,
    modifier: Modifier = Modifier,
    colors: CrestBottomBarColors = CrestBottomBarDefaults.colors(),
    labelStyle: TextStyle = CrestBottomBarDefaults.LabelStyle,
    shadowElevation: Dp = 0.dp,
    windowInsets: WindowInsets = CrestBottomBarDefaults.windowInsets,
)

class CrestBarItem(
    val label: String,
    val icon: ImageVector,
    val selectedIcon: ImageVector = icon,
)