BottomTabBar
Bottom navigation with safe areas, active states, badges and an optional main action.
Installation
npx axiom add bottom-tab-barpnpm dlx axiom add bottom-tab-baryarn dlx axiom add bottom-tab-barbun x axiom add bottom-tab-barAlso copies: icon, icon-button, badge, text, tappable and useControllableState. Installs react-native-safe-area-context.
Colors come from bottomTabBar.{fixed,floating} and bottomTabBar.item.{default,active,disabled} in the component tokens.
Usage
import { BottomTabBar } from "@/components/ui/bottom-tab-bar";
<BottomTabBar value={route} onValueChange={navigate}>
<BottomTabBar.Item value="home" icon="home" label="Home" />
<BottomTabBar.Item value="inbox" icon="inbox" label="Inbox" badge={3} />
<BottomTabBar.Item value="profile" icon="user" label="Profile" />
</BottomTabBar>;Props
BottomTabBar
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Value of the active item. Keep it aligned with the current route name. |
defaultValue | string | — | Initial active item when the bar manages its own state. |
onValueChange | (value: string) => void | — | Called when a different enabled item is pressed. This is where a router adapter navigates. |
variant | 'fixed' | 'floating' | 'fixed' | Pins the bar to the screen edge or renders it as an inset pill. |
hideOnKeyboard | boolean | true | Hides the bar while the software keyboard is open, leaving more room for the field. |
safeArea | boolean | true | Adds the bottom safe-area inset. Disable it only when the parent already provides that space. |
mainAction | ReactElement<IconButtonProps> | — | Optional raised action, dropped in the middle of the row whatever the number of items. It performs an action and never becomes the selected route. |
children | ReactNode | — | Two to five BottomTabBar.Item elements. |
style | StyleProp<ViewStyle> | — | Extra styles for the outer bar. |
BottomTabBar.Item
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Stable value used by the root to identify this destination. |
label | string | — | Short destination name displayed below the icon. |
icon | IconName | ReactNode | — | Icon shown when the item is inactive. |
activeIcon | IconName | ReactNode | icon | Optional filled or heavier icon for the active state. |
badge | number | string | boolean | — | Count, short text or dot. Counts above 99 display as 99+. |
disabled | boolean | false | Keeps the destination visible but blocks selection. |
accessibilityLabel | string | label | Spoken destination name. Badge counts are announced separately. |
testID | string | — | Identifier for navigation tests. |
The bar sets the tab accessibility role and selected state. It does not render navigation screens or own a history stack.
Use cases
Main app navigation
Use three to five stable destinations at the top level of the app. A badge can report new content without changing the route label.
<BottomTabBar value={route.name} onValueChange={router.replace}>
<BottomTabBar.Item value="home" icon="home" label="Home" />
<BottomTabBar.Item
value="inbox"
icon="inbox"
label="Inbox"
badge={unreadCount}
/>
<BottomTabBar.Item value="calendar" icon="calendar" label="Calendar" />
<BottomTabBar.Item value="profile" icon="user" label="Profile" />
</BottomTabBar>Navigation with a main action
The raised middle control is for a frequent creation action. It opens a flow but does not represent a destination.
<BottomTabBar
value={route}
onValueChange={navigate}
mainAction={
<IconButton
icon="plus"
accessibilityLabel="Create playlist"
onPress={createPlaylist}
/>
}
>
{items}
</BottomTabBar>Floating navigation over immersive content
Use the floating variant when content reaches every screen edge, such as a map. Keep enough bottom padding so controls remain reachable above the bar.
<BottomTabBar variant="floating" value={route} onValueChange={navigate}>
<BottomTabBar.Item value="map" icon="map" label="Map" />
<BottomTabBar.Item value="explore" icon="search" label="Explore" />
<BottomTabBar.Item value="saved" icon="heart" label="Saved" />
<BottomTabBar.Item value="profile" icon="user" label="Profile" />
</BottomTabBar>Navigation libraries
The component stays presentational. A small adapter maps Expo Router or React Navigation routes to value and onValueChange.
Related
- Tab
- Badge
- Snackbar, which can sit above the bar
- Hide-on-scroll