Lesson 7

Customizing Tabs

The default tab bar works well out of the box, but most apps need to match their brand. React Navigation gives you full control — from simple color changes to building an entirely custom tab bar component.

Tab Bar Colors

Set active and inactive colors through screenOptions:

<Tab.Navigator
  screenOptions={{
    tabBarActiveTintColor: '#6200ee',
    tabBarInactiveTintColor: '#999',
  }}
>
  • tabBarActiveTintColor — the color of the icon and label for the selected tab
  • tabBarInactiveTintColor — the color for unselected tabs

Tab Bar Background and Style

Style the tab bar container itself:

<Tab.Navigator
  screenOptions={{
    tabBarStyle: {
      backgroundColor: '#1a1a2e',
      borderTopWidth: 0,
      height: 60,
      paddingBottom: 8,
    },
    tabBarActiveTintColor: '#e94560',
    tabBarInactiveTintColor: '#666',
  }}
>

tabBarStyle accepts any ViewStyle properties. Common adjustments include background color, height, removing the top border, and adjusting padding.

Hiding the Tab Bar on Specific Screens

When you nest a stack inside a tab, you often want to hide the tab bar on detail screens. Use tabBarStyle with display: 'none' through options:

<Tab.Screen
  name="HomeStack"
  component={HomeStackNavigator}
  options={({ route }) => {
    const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
    return {
      tabBarStyle: routeName === 'Details' ? { display: 'none' } : undefined,
    };
  }}
/>

Import getFocusedRouteNameFromRoute from @react-navigation/native to check which screen is active inside a nested navigator.

Custom Tab Bar Labels

Control label visibility and text:

<Tab.Navigator
  screenOptions={{
    tabBarShowLabel: false, // hide all labels, show only icons
  }}
>

Or customize per-screen:

<Tab.Screen
  name="Profile"
  component={ProfileScreen}
  options={{ tabBarLabel: 'Me' }}
/>

Building a Custom Tab Bar

For full control, replace the entire tab bar with your own component using tabBar:

import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';

function CustomTabBar({ state, descriptors, navigation }) {
  return (
    <View style={tabStyles.container}>
      {state.routes.map((route, index) => {
        const { options } = descriptors[route.key];
        const label = options.tabBarLabel ?? options.title ?? route.name;
        const isFocused = state.index === index;

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true,
          });

          if (!isFocused && !event.defaultPrevented) {
            navigation.navigate(route.name);
          }
        };

        return (
          <TouchableOpacity
            key={route.key}
            onPress={onPress}
            style={[tabStyles.tab, isFocused && tabStyles.activeTab]}
          >
            <Text style={[tabStyles.label, isFocused && tabStyles.activeLabel]}>
              {label}
            </Text>
          </TouchableOpacity>
        );
      })}
    </View>
  );
}

const tabStyles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    backgroundColor: '#fff',
    paddingBottom: 20,
    paddingTop: 12,
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
  tab: { flex: 1, alignItems: 'center' },
  activeTab: { borderTopWidth: 2, borderTopColor: '#6200ee' },
  label: { fontSize: 12, color: '#999' },
  activeLabel: { color: '#6200ee', fontWeight: 'bold' },
});

Wire it into the navigator:

<Tab.Navigator tabBar={(props) => <CustomTabBar {...props} />}>
  <Tab.Screen name="Home" component={HomeScreen} />
  <Tab.Screen name="Search" component={SearchScreen} />
  <Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>

The custom tab bar receives state (current navigation state), descriptors (screen options), and navigation (the navigation object). You loop over the routes, check which is focused, and handle presses by calling navigation.navigate. This gives you complete control over layout, animation, and behavior.

In the next lesson we'll look at the Drawer navigator — a slide-out menu panel.