Cross-platform Tab View component for React Native applications with swipeable, scrollable tab interfaces and smooth animations
npx @tessl/cli install tessl/npm-react-native-tab-view@4.1.0React Native Tab View is a cross-platform Tab View component for React Native applications that enables developers to create swipeable, scrollable tab interfaces with smooth animations and gestures. It utilizes react-native-pager-view for native performance on Android and iOS platforms, while implementing PanResponder for web, macOS, and Windows compatibility.
npm install react-native-tab-view react-native-pager-viewimport {
TabView,
TabBar,
TabBarIndicator,
TabBarItem,
SceneMap,
NavigationState,
Route,
SceneRendererProps,
TabDescriptor
} from "react-native-tab-view";
// Import type aliases if needed
import type {
TabViewProps,
TabBarProps,
TabBarIndicatorProps,
TabBarItemProps
} from "react-native-tab-view";For CommonJS:
const {
TabView,
TabBar,
TabBarIndicator,
TabBarItem,
SceneMap
} = require("react-native-tab-view");import React, { useState } from 'react';
import { View, Text } from 'react-native';
import { TabView, SceneMap, NavigationState, Route } from 'react-native-tab-view';
// Define route type
type TabRoute = Route & {
title: string;
};
// Create scenes using SceneMap
const FirstRoute = () => (
<View style={{ flex: 1, backgroundColor: '#ff4081' }}>
<Text>First Tab Content</Text>
</View>
);
const SecondRoute = () => (
<View style={{ flex: 1, backgroundColor: '#673ab7' }}>
<Text>Second Tab Content</Text>
</View>
);
const renderScene = SceneMap({
first: FirstRoute,
second: SecondRoute,
});
export default function TabViewExample() {
const [index, setIndex] = useState(0);
const [routes] = useState<TabRoute[]>([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={{ width: 375 }}
/>
);
}React Native Tab View is built around several key components:
Core container component that renders swipeable tab interface with navigation state management. Provides smooth animations, gesture support, and lazy loading capabilities.
function TabView<T extends Route>({
onIndexChange,
navigationState,
renderScene,
renderTabBar,
tabBarPosition,
lazy,
swipeEnabled,
animationEnabled,
...props
}: Props<T>): JSX.Element;
interface Props<T extends Route> {
/** Callback when tab index changes */
onIndexChange: (index: number) => void;
/** Optional callback when tab is selected (before index change) */
onTabSelect?: (props: { index: number }) => void;
/** Navigation state with current index and routes */
navigationState: NavigationState<T>;
/** Function to render scene content for each route */
renderScene: (props: SceneRendererProps & { route: T }) => React.ReactNode;
/** Optional placeholder renderer for lazy-loaded scenes */
renderLazyPlaceholder?: (props: { route: T }) => React.ReactNode;
/** Optional custom tab bar renderer */
renderTabBar?: (props: SceneRendererProps & {
navigationState: NavigationState<T>;
options: Record<string, TabDescriptor<T>> | undefined;
}) => React.ReactNode;
/** Tab bar position - 'top' or 'bottom' */
tabBarPosition?: 'top' | 'bottom';
/** Enable lazy loading of scenes */
lazy?: boolean | ((props: { route: T }) => boolean);
/** Distance ahead to preload lazy scenes */
lazyPreloadDistance?: number;
/** Text direction override - 'ltr' or 'rtl' */
direction?: LocaleDirection;
/** Enable/disable swipe gestures */
swipeEnabled?: boolean;
/** Enable/disable animations */
animationEnabled?: boolean;
/** Initial layout dimensions */
initialLayout?: Partial<Layout>;
/** Style for the pager container */
pagerStyle?: StyleProp<ViewStyle>;
/** Style for the main container */
style?: StyleProp<ViewStyle>;
/** Per-route options for tab appearance and behavior */
options?: Record<string, TabDescriptor<T>>;
/** Common options applied to all tabs */
commonOptions?: TabDescriptor<T>;
}Default tab bar implementation with scrollable tabs, animated indicator, and customizable styling. Handles tab press events and provides accessibility support.
function TabBar<T extends Route>({
navigationState,
position,
layout,
jumpTo,
scrollEnabled,
renderIndicator,
onTabPress,
...props
}: Props<T>): JSX.Element;
interface Props<T extends Route> extends SceneRendererProps {
/** Navigation state */
navigationState: NavigationState<T>;
/** Enable horizontal scrolling */
scrollEnabled?: boolean;
/** Enable bounce effect on scrolling */
bounces?: boolean;
/** Active tab color */
activeColor?: string;
/** Inactive tab color */
inactiveColor?: string;
/** Press color for touch feedback */
pressColor?: string;
/** Press opacity for touch feedback */
pressOpacity?: number;
/** Per-route options for tab appearance */
options?: Record<string, TabDescriptor<T>>;
/** Custom indicator renderer */
renderIndicator?: (props: IndicatorProps<T>) => React.ReactNode;
/** Custom tab item renderer */
renderTabBarItem?: (props: TabBarItemProps<T> & { key: string }) => React.ReactElement;
/** Tab press event handler */
onTabPress?: (scene: Scene<T> & Event) => void;
/** Tab long press event handler */
onTabLongPress?: (scene: Scene<T>) => void;
/** Style for individual tabs */
tabStyle?: StyleProp<ViewStyle>;
/** Style for indicator */
indicatorStyle?: StyleProp<ViewStyle>;
/** Style for indicator container */
indicatorContainerStyle?: StyleProp<ViewStyle>;
/** Style for content container */
contentContainerStyle?: StyleProp<ViewStyle>;
/** Main container style */
style?: StyleProp<ViewStyle>;
/** Text direction for RTL support */
direction?: LocaleDirection;
/** Gap between tabs */
gap?: number;
/** Test identifier */
testID?: string;
/** Android ripple configuration */
android_ripple?: PressableAndroidRippleConfig;
}Animated indicator component that highlights the currently active tab with smooth transitions and supports both fixed and dynamic width configurations.
function TabBarIndicator<T extends Route>({
navigationState,
width,
getTabWidth,
direction,
style,
gap,
children,
...props
}: Props<T>): JSX.Element;
interface Props<T extends Route> extends SceneRendererProps {
/** Navigation state */
navigationState: NavigationState<T>;
/** Indicator width configuration */
width: 'auto' | `${number}%` | number;
/** Function to get tab width by index */
getTabWidth: (index: number) => number;
/** Text direction for RTL support */
direction: LocaleDirection;
/** Custom indicator styling */
style?: StyleProp<ViewStyle>;
/** Space between tabs */
gap?: number;
}Individual tab item component with support for labels, icons, badges, and custom rendering. Handles touch interactions and provides accessibility support.
function TabBarItem<T extends Route>({
route,
navigationState,
position,
onPress,
onLongPress,
activeColor,
inactiveColor,
...props
}: Props<T>): JSX.Element;
interface Props<T extends Route> extends TabDescriptor<T> {
/** Route object */
route: T;
/** Navigation state */
navigationState: NavigationState<T>;
/** Animated position value */
position: Animated.AnimatedInterpolation<number>;
/** Press event handler */
onPress: () => void;
/** Long press event handler */
onLongPress: () => void;
/** Active tab color */
activeColor?: string;
/** Inactive tab color */
inactiveColor?: string;
/** Tab styling */
style: StyleProp<ViewStyle>;
}Utility functions for mapping route keys to React components and rendering scenes efficiently.
/**
* Helper function to create scene renderers from component mapping
* @param scenes - Object mapping route keys to React components
* @returns Scene renderer function compatible with TabView
*/
function SceneMap<T>(scenes: { [key: string]: React.ComponentType<T> }):
(props: SceneRendererProps & { route: Route }) => React.ReactElement;/** Navigation state interface */
interface NavigationState<T extends Route> {
/** Current active tab index */
index: number;
/** Array of route objects */
routes: T[];
}
/** Base route interface */
interface Route {
/** Unique route identifier */
key: string;
/** Optional tab title */
title?: string;
/** Optional icon identifier */
icon?: string;
/** Optional accessibility label */
accessibilityLabel?: string;
/** Optional test ID */
testID?: string;
/** Optional accessibility flag */
accessible?: boolean;
}
/** Layout dimensions */
interface Layout {
/** Width in pixels */
width: number;
/** Height in pixels */
height: number;
}
/** Props passed to scene renderers */
interface SceneRendererProps {
/** Current layout dimensions */
layout: Layout;
/** Animated position value */
position: Animated.AnimatedInterpolation<number>;
/** Function to navigate to route */
jumpTo: (key: string) => void;
}
/** Scene context object */
interface Scene<T extends Route> {
route: T;
}
/** Event object with prevention capability */
interface Event {
defaultPrevented: boolean;
preventDefault(): void;
}
/** Text direction enumeration */
type LocaleDirection = 'ltr' | 'rtl';
/** Tab configuration object */
interface TabDescriptor<T extends Route> {
/** Accessibility label override */
accessibilityLabel?: string;
/** Accessibility enabled flag */
accessible?: boolean;
/** Test identifier */
testID?: string;
/** Tab label text override */
labelText?: string;
/** Allow font scaling for label */
labelAllowFontScaling?: boolean;
/** Web navigation href */
href?: string;
/** Custom label renderer function */
label?: (props: {
route: T;
labelText?: string;
focused: boolean;
color: string;
allowFontScaling?: boolean;
style?: StyleProp<TextStyle>;
}) => React.ReactNode;
/** Label text styling */
labelStyle?: StyleProp<TextStyle>;
/** Custom icon renderer function */
icon?: (props: {
route: T;
focused: boolean;
color: string;
size: number;
}) => React.ReactNode;
/** Custom badge renderer function */
badge?: (props: { route: T }) => React.ReactElement;
/** Scene container styling */
sceneStyle?: StyleProp<ViewStyle>;
}/** TypeScript type alias for TabView component props */
type TabViewProps<T extends Route> = Props<T>; // from TabView
/** TypeScript type alias for TabBar component props */
type TabBarProps<T extends Route> = Props<T>; // from TabBar
/** TypeScript type alias for TabBarIndicator component props */
type TabBarIndicatorProps<T extends Route> = Props<T>; // from TabBarIndicator
/** TypeScript type alias for TabBarItem component props */
type TabBarItemProps<T extends Route> = Props<T>; // from TabBarItem/** Listener function for animated value changes */
type Listener = (value: number) => void;
/** Props for event emitter functionality */
interface EventEmitterProps {
/** Add listener for enter events */
addEnterListener: (listener: Listener) => () => void;
}
/** Props for Pager component (internal) */
type PagerProps = Omit<
PagerViewProps,
| 'initialPage'
| 'scrollEnabled'
| 'onPageScroll'
| 'onPageSelected'
| 'onPageScrollStateChanged'
| 'keyboardDismissMode'
| 'children'
> & {
/** Keyboard dismissal behavior */
keyboardDismissMode?: 'none' | 'on-drag' | 'auto';
/** Enable/disable swipe gestures */
swipeEnabled?: boolean;
/** Enable/disable animations */
animationEnabled?: boolean;
/** Callback when swipe starts */
onSwipeStart?: () => void;
/** Callback when swipe ends */
onSwipeEnd?: () => void;
};