NavigationBar provides a bottom navigation bar for switching between primary destinations in an app. It supports icons, labels, and selection states with smooth animations.
NavigationBar
modifier
Modifier
default:"Modifier"
Modifier to be applied to the navigation bar
containerColor
Color
default:"NavigationBarDefaults.containerColor"
Background color of the navigation bar. Defaults to AppTheme.colors.background
contentColor
Color
default:"contentColorFor(containerColor)"
Color for content inside the navigation bar
windowInsets
WindowInsets
default:"NavigationBarDefaults.windowInsets"
Window insets for system bars
content
@Composable RowScope.() -> Unit
required
Content of the navigation bar, typically NavigationBarItem components
NavigationBarItem
Whether this item is currently selected
Callback invoked when the item is clicked
icon
@Composable () -> Unit
required
Icon to display for this item
modifier
Modifier
default:"Modifier"
Modifier to be applied to the item
Whether the item is enabled
label
@Composable (() -> Unit)?
default:"null"
Optional text label to display below the icon
Whether to always show the label or only when selected
colors
NavigationBarItemColors
default:"NavigationBarItemDefaults.colors()"
Colors for icon and text in different states
textStyle
TextStyle
default:"NavigationBarItemDefaults.textStyle()"
Text style for the label. Defaults to AppTheme.typography.label2
interactionSource
MutableInteractionSource
default:"MutableInteractionSource()"
Source of interactions for the item
Usage Examples
Basic Navigation Bar
var selectedItem by remember { mutableStateOf(0) }
NavigationBar {
NavigationBarItem(
selected = selectedItem == 0,
onClick = { selectedItem = 0 },
icon = {
Icon(
imageVector = Icons.Default.Home,
contentDescription = "Home"
)
},
label = { Text("Home") }
)
NavigationBarItem(
selected = selectedItem == 1,
onClick = { selectedItem = 1 },
icon = {
Icon(
imageVector = Icons.Default.Search,
contentDescription = "Search"
)
},
label = { Text("Search") }
)
NavigationBarItem(
selected = selectedItem == 2,
onClick = { selectedItem = 2 },
icon = {
Icon(
imageVector = Icons.Default.Person,
contentDescription = "Profile"
)
},
label = { Text("Profile") }
)
}
Navigation Bar Without Labels
var selectedItem by remember { mutableStateOf(0) }
NavigationBar {
NavigationBarItem(
selected = selectedItem == 0,
onClick = { selectedItem = 0 },
icon = {
Icon(
imageVector = Icons.Default.Home,
contentDescription = "Home"
)
}
)
NavigationBarItem(
selected = selectedItem == 1,
onClick = { selectedItem = 1 },
icon = {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "Favorites"
)
}
)
NavigationBarItem(
selected = selectedItem == 2,
onClick = { selectedItem = 2 },
icon = {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Settings"
)
}
)
}
Show Labels Only When Selected
var selectedItem by remember { mutableStateOf(0) }
NavigationBar {
NavigationBarItem(
selected = selectedItem == 0,
onClick = { selectedItem = 0 },
icon = { Icon(Icons.Default.Home, null) },
label = { Text("Home") },
alwaysShowLabel = false
)
NavigationBarItem(
selected = selectedItem == 1,
onClick = { selectedItem = 1 },
icon = { Icon(Icons.Default.Search, null) },
label = { Text("Search") },
alwaysShowLabel = false
)
}
Custom Colors
NavigationBar(
containerColor = Color(0xFF1E1E1E),
contentColor = Color.White
) {
NavigationBarItem(
selected = true,
onClick = { },
icon = { Icon(Icons.Default.Home, null) },
label = { Text("Home") },
colors = NavigationBarItemDefaults.colors(
selectedIconColor = Color(0xFF00BCD4),
selectedTextColor = Color(0xFF00BCD4),
unselectedIconColor = Color.White.copy(alpha = 0.6f),
unselectedTextColor = Color.White.copy(alpha = 0.6f)
)
)
}
With Badge
NavigationBarItem(
selected = selectedItem == 1,
onClick = { selectedItem = 1 },
icon = {
BadgedBox(
badge = {
Badge { Text("3") }
}
) {
Icon(Icons.Default.Notifications, null)
}
},
label = { Text("Notifications") }
)
Disabled Item
NavigationBarItem(
selected = false,
onClick = { },
enabled = false,
icon = { Icon(Icons.Default.Lock, null) },
label = { Text("Locked") }
)
Complete Example with Scaffold
enum class Screen {
HOME, SEARCH, FAVORITES, PROFILE
}
@Composable
fun MainScreen() {
var currentScreen by remember { mutableStateOf(Screen.HOME) }
Scaffold(
bottomBar = {
NavigationBar {
NavigationBarItem(
selected = currentScreen == Screen.HOME,
onClick = { currentScreen = Screen.HOME },
icon = { Icon(Icons.Default.Home, null) },
label = { Text("Home") }
)
NavigationBarItem(
selected = currentScreen == Screen.SEARCH,
onClick = { currentScreen = Screen.SEARCH },
icon = { Icon(Icons.Default.Search, null) },
label = { Text("Search") }
)
NavigationBarItem(
selected = currentScreen == Screen.FAVORITES,
onClick = { currentScreen = Screen.FAVORITES },
icon = { Icon(Icons.Default.Favorite, null) },
label = { Text("Favorites") }
)
NavigationBarItem(
selected = currentScreen == Screen.PROFILE,
onClick = { currentScreen = Screen.PROFILE },
icon = { Icon(Icons.Default.Person, null) },
label = { Text("Profile") }
)
}
}
) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
when (currentScreen) {
Screen.HOME -> HomeScreen()
Screen.SEARCH -> SearchScreen()
Screen.FAVORITES -> FavoritesScreen()
Screen.PROFILE -> ProfileScreen()
}
}
}
}
Styling Options
Navigation Bar Colors
NavigationBar(
containerColor = AppTheme.colors.surface,
contentColor = AppTheme.colors.onSurface
) { }
Item Colors
NavigationBarItemDefaults.colors(
selectedIconColor: Color = AppTheme.colors.onBackground,
selectedTextColor: Color = AppTheme.colors.onBackground,
unselectedIconColor: Color = AppTheme.colors.onBackground.copy(alpha = 0.65f),
unselectedTextColor: Color = AppTheme.colors.onBackground.copy(alpha = 0.65f),
disabledIconColor: Color = AppTheme.colors.onBackground.copy(alpha = 0.3f),
disabledTextColor: Color = AppTheme.colors.onBackground.copy(alpha = 0.3f)
)
Features
- Smooth Animations: Icon and label animate during selection with 100ms duration
- Adaptive Layout: Items automatically distribute available width
- Window Insets: Proper handling of system navigation bars
- Accessibility: Full semantic support with Role.Tab
- RTL Support: Correct layout in right-to-left languages
- State Management: Built-in selection state handling
- Custom Typography: Configurable text style for labels
Design Guidelines
- Item Count: Use 3-5 navigation items for optimal usability
- Icons: Use clear, recognizable icons
- Labels: Keep labels short (1-2 words)
- Selection: Always have one item selected
- Disabled States: Use sparingly
Constants
- Height: 80dp (NavigationBarDefaults.NavigationBarHeight)
- Horizontal Padding: 8dp per item
- Vertical Padding: 18dp per item
- Animation Duration: 100ms
Source Reference
NavigationBar component implementation: components-lab/src/commonMain/kotlin/com/nomanr/lumo/ui/components/NavigationBar.kt