Skip to content

CollapsibleTabsShell and useCollapsibleTabs() ​

<CollapsibleTabsShell> ​

The lower-level primitive if you don't want the tab-view-shaped API. Authors the header, tab bar and pages as ordinary React children; the platform re-parents them by nativeID and owns every scroll-driven pixel. CollapsibleTabView is a thin layer over it.

tsx
import { CollapsibleTabsShell } from 'react-native-collapsible-tabs-native';

<CollapsibleTabsShell
  ref={tabs}
  header={<ProfileHeader />}
  tabBar={<MyTabs index={index} onIndexChange={setIndex} />}
  pages={[<Posts key="posts" />, <About key="about" />]}
  index={index}
  onIndexChange={setIndex}
  collapseMode="classic"
  pinTabBar
  allowFullCollapse
  refreshing={refreshing}
  onRefresh={reload}
  onHeaderOffsetChange={onHeaderOffsetChange}
  lazy
/>
propnotes
headerthe collapsing header node
tabBarthe pinned tab strip node
pagesone React tree per tab, in tab order
index / onIndexChangecontrolled page
everything elsethe same collapse, refresh and per-frame event props as CollapsibleTabView, and the same ref

The exported ids SHELL_BANDS_ID, SHELL_HEADER_ID, SHELL_TABBAR_ID and shellPageId(i) name the nativeIDs the shell mounts, for anyone building on the native contract directly. Since 0.8.0 the header and tab bar sit inside a tabs-bands scroll view that the shell drives; see How it works.

useCollapsibleTabs() ​

ts
const { isNativeShell, contentPaddingTop, activeIndex } = useCollapsibleTabs();
fieldnotes
isNativeShelltrue inside a shell; false when the hook is used outside one, so a shared list component can fall back to zero padding
contentPaddingTopheader + tab-bar height in dp; what a tab body must pad by
activeIndexthe controlled index

For custom tab bodies that don't go through createTabList, or for anything else in a page that needs to know where the bands end (a pinned overlay at top: contentPaddingTop, a FlashList stickyHeaderConfig.offset).

Released under the MIT License.