Cross-platform Tab View component for React Native applications with swipeable, scrollable tab interfaces and smooth animations
—
The TabBarItem component represents an individual tab in the tab bar. It handles rendering of labels, icons, badges, and provides touch interaction capabilities with accessibility support. Each tab item automatically adapts its appearance based on the active/inactive state.
Individual tab item component with support for labels, icons, badges, and custom rendering.
/**
* Individual tab item component for rendering single tabs
* @param props - TabBarItem configuration and interaction handlers
* @returns JSX element containing the tab item interface
*/
function TabBarItem<T extends Route>(props: Props<T>): JSX.Element;
interface Props<T extends Route> extends TabDescriptor<T> {
/** Animated position value for state transitions */
position: Animated.AnimatedInterpolation<number>;
/** Route object associated with this tab */
route: T;
/** Complete navigation state */
navigationState: NavigationState<T>;
/** Active tab color override */
activeColor?: string;
/** Inactive tab color override */
inactiveColor?: string;
/** Press ripple color (Android) */
pressColor?: string;
/** Press opacity effect value */
pressOpacity?: number;
/** Layout measurement event handler */
onLayout?: (event: LayoutChangeEvent) => void;
/** Required press event handler */
onPress: () => void;
/** Required long press event handler */
onLongPress: () => void;
/** Default tab width for layout calculations */
defaultTabWidth?: number;
/** Tab container styling */
style: StyleProp<ViewStyle>;
/** Android ripple effect configuration */
android_ripple?: PressableAndroidRippleConfig;
}Usage Examples:
import React from 'react';
import { TabBar, TabBarItem } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/MaterialIcons';
// Custom tab item with icon
const renderTabBar = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
icon={({ focused, color }) => (
<Icon
name={getIconName(route.key)}
size={24}
color={color}
/>
)}
activeColor="#1976d2"
inactiveColor="#757575"
/>
)}
/>
);
// Tab item with badge
const renderTabBarWithBadges = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
badge={({ route }) => {
const count = getBadgeCount(route.key);
return count > 0 ? (
<View style={styles.badge}>
<Text style={styles.badgeText}>{count}</Text>
</View>
) : null;
}}
/>
)}
/>
);
// Custom label rendering
const renderTabBarWithCustomLabels = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
label={({ focused, color, labelText }) => (
<Text
style={[
{ color, fontSize: 12 },
focused && { fontWeight: 'bold', fontSize: 14 }
]}
>
{labelText?.toUpperCase()}
</Text>
)}
/>
)}
/>
);Configure tab appearance and behavior through TabDescriptor interface.
/**
* Configuration interface for tab appearance and behavior
*/
interface TabDescriptor<T extends Route> {
/** Override accessibility label */
accessibilityLabel?: string;
/** Override accessibility enabled flag */
accessible?: boolean;
/** Test identifier for automation */
testID?: string;
/** Override tab label text */
labelText?: string;
/** Allow font scaling for accessibility */
labelAllowFontScaling?: boolean;
/** Web navigation href */
href?: string;
/** Custom label renderer function */
label?: (props: LabelProps<T>) => React.ReactNode;
/** Label text styling */
labelStyle?: StyleProp<TextStyle>;
/** Custom icon renderer function */
icon?: (props: IconProps<T>) => React.ReactNode;
/** Custom badge renderer function */
badge?: (props: BadgeProps<T>) => React.ReactElement;
/** Scene container styling */
sceneStyle?: StyleProp<ViewStyle>;
}
/**
* Props for custom label renderers
*/
interface LabelProps<T extends Route> {
route: T;
labelText?: string;
focused: boolean;
color: string;
allowFontScaling?: boolean;
style?: StyleProp<TextStyle>;
}
/**
* Props for custom icon renderers
*/
interface IconProps<T extends Route> {
route: T;
focused: boolean;
color: string;
size: number;
}
/**
* Props for custom badge renderers
*/
interface BadgeProps<T extends Route> {
route: T;
}Tab items automatically animate between active and inactive states.
/**
* Animation configuration for tab state transitions
*/
interface TabAnimationConfig {
/** Default active color */
DEFAULT_ACTIVE_COLOR: 'rgba(255, 255, 255, 1)';
/** Default inactive color */
DEFAULT_INACTIVE_COLOR: 'rgba(255, 255, 255, 0.7)';
/** Default icon size */
ICON_SIZE: 24;
}
/**
* Opacity calculation functions for smooth transitions
*/
interface OpacityCalculations {
/** Calculate active state opacity */
getActiveOpacity: (
position: Animated.AnimatedInterpolation<number>,
routesLength: number,
tabIndex: number
) => Animated.AnimatedInterpolation<number> | number;
/** Calculate inactive state opacity */
getInactiveOpacity: (
position: Animated.AnimatedInterpolation<number>,
routesLength: number,
tabIndex: number
) => Animated.AnimatedInterpolation<number> | number;
}Animation Examples:
// Custom animated tab item
const AnimatedTabItem = ({ route, focused, position, ...props }) => {
const scale = position.interpolate({
inputRange: [route.index - 1, route.index, route.index + 1],
outputRange: [0.9, 1.1, 0.9],
extrapolate: 'clamp',
});
return (
<Animated.View style={{ transform: [{ scale }] }}>
<TabBarItem {...props} route={route} />
</Animated.View>
);
};TabBarItem handles platform differences automatically.
/**
* Android-specific ripple configuration
*/
interface PressableAndroidRippleConfig {
/** Ripple effect color */
color?: string;
/** Whether ripple extends beyond component bounds */
borderless?: boolean;
/** Ripple radius */
radius?: number;
}
/**
* Default Android ripple configuration
*/
const ANDROID_RIPPLE_DEFAULT: PressableAndroidRippleConfig = {
borderless: true
};Platform Examples:
// Platform-specific styling
const renderPlatformTabBar = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
android_ripple={{
color: '#e3f2fd',
borderless: true,
radius: 32,
}}
style={Platform.select({
ios: { borderRadius: 10 }, // iPad hover effect
android: { backgroundColor: 'transparent' },
default: { backgroundColor: 'transparent' },
})}
/>
)}
/>
);TabBarItem provides comprehensive accessibility features.
/**
* Accessibility configuration
*/
interface AccessibilityConfig {
/** ARIA role for web accessibility */
role: 'tab';
/** ARIA label attribute */
'aria-label': string;
/** ARIA selected state */
'aria-selected': boolean;
/** React Native accessibility properties */
accessible: boolean;
accessibilityLabel: string;
}Accessibility Examples:
// Enhanced accessibility
const renderAccessibleTabBar = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
accessible={true}
accessibilityLabel={`${route.title} tab`}
accessibilityHint={`Navigate to ${route.title} screen`}
testID={`tab-${route.key}`}
/>
)}
/>
);Complete control over tab item appearance and layout.
/**
* Default tab item styles
*/
interface DefaultTabStyles {
/** Icon container styling */
icon: {
margin: 2;
};
/** Main item container */
item: {
flex: 1;
alignItems: 'center';
justifyContent: 'center';
padding: 10;
minHeight: 48;
};
/** Badge positioning */
badge: {
position: 'absolute';
top: 0;
end: 0;
};
/** Pressable container */
pressable: {
backgroundColor: 'transparent';
};
}Advanced Styling Examples:
// Custom tab item styling
const renderStyledTabBar = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, focused, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
style={[
styles.tabItem,
focused && styles.tabItemFocused,
{ minWidth: 100 }
]}
labelStyle={[
styles.tabLabel,
focused && styles.tabLabelFocused,
]}
pressOpacity={0.7}
/>
)}
/>
);
const styles = StyleSheet.create({
tabItem: {
borderRadius: 8,
marginHorizontal: 4,
paddingVertical: 8,
},
tabItemFocused: {
backgroundColor: 'rgba(33, 150, 243, 0.1)',
},
tabLabel: {
fontSize: 12,
fontWeight: '500',
},
tabLabelFocused: {
fontSize: 14,
fontWeight: '700',
},
});Handle user interactions with custom logic.
/**
* Event handler types
*/
interface EventHandlers {
/** Press event handler */
onPress: () => void;
/** Long press event handler */
onLongPress: () => void;
/** Layout measurement handler */
onLayout?: (event: LayoutChangeEvent) => void;
}
/**
* Layout change event structure
*/
interface LayoutChangeEvent {
nativeEvent: {
layout: {
x: number;
y: number;
width: number;
height: number;
};
};
}Event Handling Examples:
// Custom event handling
const renderInteractiveTabBar = (props) => (
<TabBar
{...props}
renderTabBarItem={({ route, onPress, onLongPress, ...itemProps }) => (
<TabBarItem
{...itemProps}
route={route}
onPress={() => {
console.log('Tab pressed:', route.key);
onPress();
}}
onLongPress={() => {
console.log('Tab long pressed:', route.key);
showTabContextMenu(route);
onLongPress();
}}
onLayout={(event) => {
const { width, height } = event.nativeEvent.layout;
console.log(`Tab ${route.key} size:`, { width, height });
}}
/>
)}
/>
);Install with Tessl CLI
npx tessl i tessl/npm-react-native-tab-view