Gathering detailed insights and metrics for react-native-collapsible-tab-view-navigation
Gathering detailed insights and metrics for react-native-collapsible-tab-view-navigation
Gathering detailed insights and metrics for react-native-collapsible-tab-view-navigation
Gathering detailed insights and metrics for react-native-collapsible-tab-view-navigation
A cross-platform Collapsible Tab View component for React Native
npm install react-native-collapsible-tab-view-navigation
Typescript
Module System
Node Version
NPM Version
TypeScript (91.58%)
Kotlin (2.93%)
Ruby (2.05%)
Objective-C++ (1.72%)
JavaScript (1.27%)
Objective-C (0.21%)
Shell (0.1%)
Swift (0.07%)
C (0.06%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
996 Stars
512 Commits
208 Forks
7 Watchers
27 Branches
15 Contributors
Updated on Jul 13, 2025
Latest Version
0.0.0-alpha.0
Package Id
react-native-collapsible-tab-view-navigation@0.0.0-alpha.0
Unpacked Size
34.83 kB
Size
7.07 kB
File Count
21
NPM Version
6.14.7
Node Version
14.7.0
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
6
15
React Native Collapsible Tab View is a versatile library for creating collapsible tab views using Reanimated.
Credits
The react-native-tab-view example app was used as a template for the demos.
Default | Snap | revealHeaderOnScroll | revealHeaderOnScroll + Snap |
---|---|---|---|
![]() | ![]() | ![]() | ![]() |
To install the library, open a terminal in your project's root directory and run:
1yarn add react-native-collapsible-tab-view react-native-pager-view
Then, add Reanimated, follow the official installation guide.
1import React from 'react' 2import { View, StyleSheet, ListRenderItem } from 'react-native' 3import { Tabs } from 'react-native-collapsible-tab-view' 4 5const HEADER_HEIGHT = 250 6 7const DATA = [0, 1, 2, 3, 4] 8const identity = (v: unknown): string => v + '' 9 10const Header = () => { 11 return <View style={styles.header} /> 12} 13 14const Example: React.FC = () => { 15 const renderItem: ListRenderItem<number> = React.useCallback(({ index }) => { 16 return ( 17 <View style={[styles.box, index % 2 === 0 ? styles.boxB : styles.boxA]} /> 18 ) 19 }, []) 20 21 return ( 22 <Tabs.Container 23 renderHeader={Header} 24 headerHeight={HEADER_HEIGHT} // optional 25 > 26 <Tabs.Tab name="A"> 27 <Tabs.FlatList 28 data={DATA} 29 renderItem={renderItem} 30 keyExtractor={identity} 31 /> 32 </Tabs.Tab> 33 <Tabs.Tab name="B"> 34 <Tabs.ScrollView> 35 <View style={[styles.box, styles.boxA]} /> 36 <View style={[styles.box, styles.boxB]} /> 37 </Tabs.ScrollView> 38 </Tabs.Tab> 39 </Tabs.Container> 40 ) 41} 42 43const styles = StyleSheet.create({ 44 box: { 45 height: 250, 46 width: '100%', 47 }, 48 boxA: { 49 backgroundColor: 'white', 50 }, 51 boxB: { 52 backgroundColor: '#D8D8D8', 53 }, 54 header: { 55 height: HEADER_HEIGHT, 56 width: '100%', 57 backgroundColor: '#2196f3', 58 }, 59}) 60 61export default Example 62
To enable scrolling from the header, follow these steps:
HeaderComponent
does not contain touchable components, set the pointerEvents
prop to 'none'
.HeaderComponent
does contain touchable components, set the pointerEvents
prop to 'box-none'
to ensure they function properly.Note: If any child component within the HeaderComponent
should not respond to touches, such as an <Image />
element, set its pointerEvents
prop to 'none'
. Otherwise, it may unintentionally become the target of a touch gesture on iOS devices and prevent scrolling.
Basic usage looks like this:
1import { Tabs } from 'react-native-collapsible-tab-view' 2 3const Example = () => { 4 return ( 5 <Tabs.Container renderHeader={MyHeader}> 6 <Tabs.Tab name="A"> 7 <ScreenA /> 8 </Tabs.Tab> 9 <Tabs.Tab name="B"> 10 <ScreenB /> 11 </Tabs.Tab> 12 </Tabs.Container> 13 ) 14}
name | type | default | description |
---|---|---|---|
allowHeaderOverscroll | boolean | undefined | false | Whether the header moves down during overscrolling (for example on pull-to-refresh on iOS) or sticks to the top |
cancelLazyFadeIn | boolean | undefined | ||
cancelTranslation | boolean | undefined | ||
containerStyle | StyleProp<ViewStyle> | ||
headerContainerStyle | StyleProp<AnimateStyle<ViewStyle>> | ||
headerHeight | number | undefined | Is optional, but will optimize the first render. | |
initialTabName | string | undefined | ||
lazy | boolean | undefined | If lazy, will mount the screens only when the tab is visited. There is a default fade in transition. | |
minHeaderHeight | number | undefined | Header minimum height when collapsed | |
onIndexChange | ((index: number) => void) | undefined | Callback fired when the index changes. It receives the current index. | |
onTabChange | (data: { prevIndex: number index: number prevTabName: T tabName: T }) => void | Callback fired when the tab changes. It receives the previous and current index and tabnames. | |
pagerProps | Omit<FlatListProps<number>, 'data' | 'keyExtractor' | 'renderItem' | 'horizontal' | 'pagingEnabled' | 'onScroll' | 'showsHorizontalScrollIndicator' | 'getItemLayout'> | Props passed to the pager. If you want for example to disable swiping, you can pass { scrollEnabled: false } | |
renderHeader | (props: TabBarProps<TabName>) => React.ReactElement | null | ||
renderTabBar | (props: TabBarProps<TabName>) => React.ReactElement | null | (props: TabBarProps<TabName>) => MaterialTabBar | |
revealHeaderOnScroll | boolean | undefined | Reveal header when scrolling down. Implements diffClamp. | |
snapThreshold | number | null | undefined | null | Percentage of header height to define as the snap point. A number between 0 and 1, or null to disable snapping. |
tabBarHeight | number | undefined | Is optional, but will optimize the first render. | |
width | number | undefined | Custom width of the container. Defaults to the window width. |
Wrap your screens with Tabs.Tab
. Basic usage looks like this:
1<Tabs.Container ...> 2 <Tabs.Tab name="A" label="First Tab"> 3 <ScreenA /> 4 </Tabs.Tab> 5 <Tabs.Tab name="B"> 6 <ScreenA /> 7 </Tabs.Tab> 8</Tabs.Container>
name | type |
---|---|
label | string | ((props: TabItemProps<T>) => ReactNode) | undefined |
name | T |
Typically used internally, but if you want to mix lazy and regular screens you can wrap the lazy ones with this component.
name | type |
---|---|
cancelLazyFadeIn | boolean | undefined |
startMounted | boolean | undefined |
Use like a regular FlatList.
Use like a regular FlashList.
Use like a regular MasonryFlashList.
Use like a regular ScrollView.
Use like a regular SectionList.
You can pass a ref to Tabs.Container
.
1const ref = React.useRef()
2<Tabs.Container ref={ref}>
method | type |
---|---|
jumpToTab | (name: T) => boolean |
setIndex | (index: number) => boolean |
getFocusedTab | () => T |
getCurrentIndex | () => number |
useCollapsibleStyle
This hook provides access to key styles for the collapsible tab view. It can be used to obtain the progressViewOffset
and pass it to the RefreshControl
of the scroll view.
1const { 2 contentContainerStyle, 3 progressViewOffset, 4 style, 5} = useCollapsibleStyle()
name | type |
---|---|
contentContainerStyle | { minHeight: number; paddingTop: number; } |
progressViewOffset | number |
style | { width: number; } |
useAnimatedTabIndex
This hook returns an animated value representing the current tab index. As the tab view can be in between panes while swiping, this value is a floating-point number.
1const tabIndex = useAnimatedTabIndex()
useFocusedTab
This hook returns the name of the currently focused tab.
1const focusedTab = useFocusedTab()
useHeaderMeasurements
This hook returns the top distance and the header height. For an example of how to use this, check out the animated header example in the example folder.
1const { top, height } = useHeaderMeasurements()
This hook returns the vertical scroll position of the current tab as an Animated SharedValue.
Since this library requires handling the onScroll
event for its functionality, this is the only way to react to changes in the scroll position of the underlying scrollable component.
1const scrollY = useCurrentTabScrollY()
Any additional props are passed to the pressable component.
name | type | description |
---|---|---|
activeColor | string | undefined | Color applied to the label when active |
inactiveColor | string | undefined | Color applied to the label when inactive |
inactiveOpacity | number | undefined | |
index | number | |
indexDecimal | SharedValue<number> | |
label | string | ((props: TabItemProps<T>) => ReactNode) | |
labelStyle | StyleProp<AnimateStyle<TextStyle>> | Style to apply to the tab item label |
name | T | |
onLayout | (((event: LayoutChangeEvent) => void) & ((event: LayoutChangeEvent) => void)) | undefined | Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}. |
onPress | (name: T) => void | |
pressColor | string | undefined | |
pressOpacity | number | undefined | |
scrollEnabled | boolean | undefined | |
style | StyleProp<ViewStyle> | Either view styles or a function that receives a boolean reflecting whether the component is currently pressed and returns view styles. |
Refer to this open issue. We utilize scrollTo to synchronize the unfocused tabs. While it is intended for use with ScrollView
, it works well with FlatList
, until the RefreshControl
is added. Note that this issue occurs only on Android.
Workaround: Check out the Android Shared Pull To Refresh
example in the expo app. You can implement a single pull-to-refresh for the Tabs.Container
.
When using the stickyHeaderIndices
prop on a FlatList or stickySectionHeadersEnabled
on a SectionList, the sticky elements do not scroll up as the header collapses. This issue is specific to iOS.
See #136.
ref.setIndex
This is not an issue per se, but it's essential to be aware of it. When using containerRef.current.setIndex(i)
, if you set it to the current index, the screen will scroll to the top. You can prevent this behavior as follows:
1const index = pageRef.current?.getCurrentIndex() 2if (index !== nextIndex) { 3 pageRef.current?.setIndex(nextIndex) 4}
If you do not require a full-featured tab view, consider another option: a simple segmented control / material tab bar without swiping or snapping, using only the React Native Animated API.
While developing, you can run the example app to test your changes.
First run yarn
in root:
1yarn
Then prepare the example:
1cd example 2yarn
Then run the example:
yarn ios
Please follow the angular commit message format.
Make sure your code passes TypeScript and ESLint. Run the following to verify:
1yarn typescript 2yarn lint
To fix formatting errors, run the following:
1yarn lint -- --fix
Edit the README_TEMPLATE, or update the docstrings inside the src
folder, and run:
1yarn docs
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
binaries present in source code
Details
Reason
Found 5/19 approved changesets -- score normalized to 2
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
30 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-14
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More