Bottom tab navigator following iOS design guidelines for React Navigation
—
Comprehensive tab bar customization including appearance, behavior, animations, and custom components for creating highly customized bottom tab navigation experiences.
Customize the display and behavior of tab labels.
interface TabLabelOptions {
/**
* Title string of a tab displayed in the tab bar or a function that returns a React.Node.
* When undefined, scene title is used.
*/
tabBarLabel?: string | ((props: {
focused: boolean;
color: string;
position: LabelPosition;
children: string;
}) => React.ReactNode);
/**
* Whether the tab label should be visible. Defaults to `true`.
*/
tabBarShowLabel?: boolean;
/**
* Whether the label is shown below the icon or beside the icon.
* By default, the position is chosen automatically based on device width.
*/
tabBarLabelPosition?: LabelPosition;
/**
* Style object for the tab label.
*/
tabBarLabelStyle?: StyleProp<TextStyle>;
/**
* Whether label font should scale to respect Text Size accessibility settings.
*/
tabBarAllowFontScaling?: boolean;
}
type LabelPosition = 'beside-icon' | 'below-icon';Usage Examples:
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarLabel: 'My Home',
tabBarLabelStyle: {
fontSize: 12,
fontWeight: 'bold',
},
tabBarLabelPosition: 'below-icon',
tabBarAllowFontScaling: false,
}}
/>
// Dynamic label
<Tab.Screen
name="Messages"
component={MessagesScreen}
options={{
tabBarLabel: ({ focused, color }) => (
<Text style={{ color, fontWeight: focused ? 'bold' : 'normal' }}>
Messages
</Text>
),
}}
/>Customize tab icons with full control over appearance and behavior.
interface TabIconOptions {
/**
* A function that returns a React.Node to display in the tab bar.
*/
tabBarIcon?: (props: {
focused: boolean;
color: string;
size: number;
}) => React.ReactNode;
/**
* Style object for the tab icon.
*/
tabBarIconStyle?: StyleProp<TextStyle>;
}Usage Examples:
import Icon from 'react-native-vector-icons/Ionicons';
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Icon
name={focused ? 'home' : 'home-outline'}
size={size}
color={color}
/>
),
tabBarIconStyle: {
marginTop: 2,
},
}}
/>Display badges on tabs for notifications and status indicators.
interface TabBadgeOptions {
/**
* Text to show in a badge on the tab icon.
*/
tabBarBadge?: number | string;
/**
* Custom style for the tab bar badge.
* You can specify a background color or text color here.
*/
tabBarBadgeStyle?: StyleProp<TextStyle>;
}Usage Examples:
<Tab.Screen
name="Messages"
component={MessagesScreen}
options={{
tabBarBadge: 5,
tabBarBadgeStyle: {
backgroundColor: 'red',
color: 'white',
},
}}
/>
// Dynamic badge
<Tab.Screen
name="Notifications"
component={NotificationsScreen}
options={({ route }) => ({
tabBarBadge: route.params?.unreadCount > 0 ? route.params.unreadCount : undefined,
})}
/>Control the visual appearance of tabs including colors and backgrounds.
interface TabAppearanceOptions {
/**
* Color for the icon and label in the active tab.
*/
tabBarActiveTintColor?: string;
/**
* Color for the icon and label in the inactive tabs.
*/
tabBarInactiveTintColor?: string;
/**
* Background color for the active tab.
*/
tabBarActiveBackgroundColor?: string;
/**
* Background color for the inactive tabs.
*/
tabBarInactiveBackgroundColor?: string;
/**
* Style object for the tab item container.
*/
tabBarItemStyle?: StyleProp<ViewStyle>;
/**
* Variant of the tab bar. Defaults to `uikit`.
*/
tabBarVariant?: Variant;
}
type Variant = 'uikit' | 'material';Usage Examples:
<Tab.Navigator
screenOptions={{
tabBarActiveTintColor: '#e91e63',
tabBarInactiveTintColor: 'gray',
tabBarActiveBackgroundColor: '#f0f0f0',
tabBarItemStyle: {
paddingVertical: 8,
},
tabBarVariant: 'material',
}}
>
{/* screens */}
</Tab.Navigator>Comprehensive styling options for the entire tab bar.
interface TabBarStylingOptions {
/**
* Style object for the tab bar container.
*/
tabBarStyle?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
/**
* Function which returns a React Element to use as background for the tab bar.
* When using `BlurView`, make sure to set `position: 'absolute'` in `tabBarStyle`.
*/
tabBarBackground?: () => React.ReactNode;
/**
* Position of the tab bar on the screen. Defaults to `bottom`.
*/
tabBarPosition?: 'bottom' | 'left' | 'right' | 'top';
}Usage Examples:
import { BlurView } from '@react-native-community/blur';
<Tab.Navigator
screenOptions={{
tabBarStyle: {
position: 'absolute',
backgroundColor: 'transparent',
borderTopWidth: 0,
elevation: 0,
},
tabBarBackground: () => (
<BlurView
style={{ ...StyleSheet.absoluteFillObject }}
blurType="light"
blurAmount={10}
/>
),
tabBarPosition: 'bottom',
}}
>
{/* screens */}
</Tab.Navigator>Replace default tab buttons with completely custom components.
interface TabButtonOptions {
/**
* Function which returns a React element to render as the tab bar button.
* Renders `PlatformPressable` by default.
*/
tabBarButton?: (props: BottomTabBarButtonProps) => React.ReactNode;
}
interface BottomTabBarButtonProps extends Omit<
React.ComponentProps<typeof PlatformPressable>,
'style'
> {
href?: string;
children: React.ReactNode;
style?: StyleProp<ViewStyle>;
onPress?: (
e: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
) => void;
}Usage Examples:
import { Pressable } from 'react-native';
<Tab.Screen
name="Special"
component={SpecialScreen}
options={{
tabBarButton: (props) => (
<Pressable
{...props}
style={[
props.style,
{
backgroundColor: 'purple',
borderRadius: 25,
margin: 5,
}
]}
/>
),
}}
/>Configure tab bar behavior when the keyboard is displayed.
interface KeyboardInteractionOptions {
/**
* Whether the tab bar gets hidden when the keyboard is shown. Defaults to `false`.
*/
tabBarHideOnKeyboard?: boolean;
/**
* Animation config for showing and hiding the tab bar when the keyboard is shown/hidden.
*/
tabBarVisibilityAnimationConfig?: {
show?: TabBarVisibilityAnimationConfig;
hide?: TabBarVisibilityAnimationConfig;
};
}
type TabBarVisibilityAnimationConfig =
| TimingKeyboardAnimationConfig
| SpringKeyboardAnimationConfig;
interface TimingKeyboardAnimationConfig {
animation: 'timing';
config?: Omit<
Partial<Animated.TimingAnimationConfig>,
'toValue' | 'useNativeDriver'
>;
}
interface SpringKeyboardAnimationConfig {
animation: 'spring';
config?: Omit<
Partial<Animated.SpringAnimationConfig>,
'toValue' | 'useNativeDriver'
>;
}Usage Examples:
<Tab.Navigator
screenOptions={{
tabBarHideOnKeyboard: true,
tabBarVisibilityAnimationConfig: {
show: {
animation: 'spring',
config: {
damping: 15,
stiffness: 150,
},
},
hide: {
animation: 'timing',
config: {
duration: 200,
},
},
},
}}
>
{/* screens */}
</Tab.Navigator>Accessibility features for screen readers and assistive technologies.
interface AccessibilityOptions {
/**
* Accessibility label for the tab button. This is read by the screen reader when the user taps the tab.
* It's recommended to set this if you don't have a label for the tab.
*/
tabBarAccessibilityLabel?: string;
/**
* ID to locate this tab button in tests.
*/
tabBarButtonTestID?: string;
}Usage Examples:
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarAccessibilityLabel: 'Home tab, double tap to navigate to home screen',
tabBarButtonTestID: 'home-tab-button',
}}
/>For advanced customization, you can replace the entire tab bar component.
interface BottomTabBarProps {
state: TabNavigationState<ParamListBase>;
descriptors: BottomTabDescriptorMap;
navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>;
insets: EdgeInsets;
}
const BottomTabBar: React.ComponentType<BottomTabBarProps & {
style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
}>;Usage Examples:
import { BottomTabBar } from '@react-navigation/bottom-tabs';
function CustomTabBar(props) {
return (
<View>
<BottomTabBar {...props} />
<View style={{ height: 20, backgroundColor: 'blue' }} />
</View>
);
}
<Tab.Navigator tabBar={(props) => <CustomTabBar {...props} />}>
{/* screens */}
</Tab.Navigator>Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--bottom-tabs