Skip to content

TabBar

The TabBar provides primary navigation between main sections of the app. It uses a minimal design with gold accent indicators and haptic feedback.

CAST
BROWSE
LEARN
HISTORY

CAST
BROWSE
LEARN
HISTORY
1Gold indicator dot (active)
2Uppercase label
3Touch target (full width)
ElementActiveInactive
Indicator4x4px gold dotHidden
LabelGold, medium weightGray, regular weight
TouchFull tab area respondsFull tab area responds

BROWSE

Default state for unselected tabs.

CAST

Currently selected tab with gold indicator and label.

LEARN

Visual feedback during touch (70% opacity).


The TabBar triggers selection haptics on every tap:

const onPress = () => {
haptics.selection(); // Light haptic feedback
navigation.navigate(route.name);
};

The TabBar automatically adjusts for device safe areas (notch, home indicator):

const bottomPadding = insets.bottom > 0
? insets.bottom
: theme.spacing.compact;
DeviceBottom Padding
iPhone with Face ID~34px
iPhone with Home Button12px (fallback)
Android12px (fallback)

PropertyValue
Base Height64px
Label Size11px
Letter Spacing0.5px (wide)
Indicator Size4x4px
BackgroundSurface @ 95% opacity
Border Top1px border color

The TabBar receives standard React Navigation bottom tab props:

PropTypeDescription
stateTabNavigationStateCurrent navigation state
descriptorsBottomTabDescriptorMapTab configuration
navigationNavigationPropNavigation object
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { CustomTabBar } from '@synchronicity/react-native';
const Tab = createBottomTabNavigator();
function Navigation() {
return (
<Tab.Navigator
tabBar={(props) => <CustomTabBar {...props} />}
screenOptions={{
headerShown: false,
}}
>
<Tab.Screen name="Cast" component={CastScreen} />
<Tab.Screen name="Browse" component={BrowseScreen} />
<Tab.Screen name="Learn" component={LearnScreen} />
<Tab.Screen name="History" component={HistoryScreen} />
</Tab.Navigator>
);
}

We use text labels instead of icons for several reasons:

  1. Clarity: Words are unambiguous
  2. Accessibility: Better for screen readers
  3. Contemplative design: Less visual noise
  4. Brand: Unique, memorable navigation

The small gold dot is chosen over:

  • Underlines (too heavy)
  • Background fills (too prominent)
  • Icon changes (we don’t use icons)

The dot is subtle but clearly visible, drawing the eye without demanding it.

Uppercase with wide letter spacing creates:

  • Visual rhythm
  • Clear separation from content
  • Intentional, ceremonial feel

  • Role: Each tab is accessibilityRole="button"
  • Label: Clear text description
  • State: accessibilityState=&#123;&#123; selected: isFocused &#125;&#125;
  • Hint: Navigate to the selected tab
  • Touch target: Full tab width, 64px+ height
<TouchableOpacity
accessibilityRole="button"
accessibilityLabel="Cast"
accessibilityState={{ selected: true }}
accessibilityHint="Navigate to Cast tab"
>
...
</TouchableOpacity>

import { CustomTabBar } from '@synchronicity/react-native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function AppNavigator() {
return (
<Tab.Navigator
tabBar={(props) => <CustomTabBar {...props} />}
screenOptions={{
headerShown: false,
tabBarHideOnKeyboard: true,
}}
>
<Tab.Screen
name="Cast"
component={CastScreen}
options={{ title: 'Cast' }}
/>
<Tab.Screen
name="Browse"
component={BrowseScreen}
options={{ title: 'Browse' }}
/>
<Tab.Screen
name="Learn"
component={LearnScreen}
options={{ title: 'Learn' }}
/>
<Tab.Screen
name="History"
component={HistoryScreen}
options={{ title: 'History' }}
/>
</Tab.Navigator>
);
}