🚧 True Sheet 4.0 beta rewrites the layout engine. npx expo install @lodev09/react-native-true-sheet@beta Migration guide
Guides

Adding Footer

Add a footer component pinned to the bottom of the sheet.

Do you need action buttons on the sheet? Or perhaps a small banner at the bottom? We've got you covered!

TrueSheet provides first-class support for a Footer component. The footer is pinned to the bottom of the sheet, takes up space below the content, and its height is included in the auto detent calculation.

How?

Define your footer component.

const SomeFooter = () => {
  return (
    <View>
      <Text>My Foot-er is Awesome.</Text>
    </View>
  )
}

Stick it in the footer.

const App = () => {
  return (
    <TrueSheet footer={SomeFooter}>
      <View />
    </TrueSheet>
  )
}

For best performance, use ReactElement instead!

const App = () => {
  return (
    <TrueSheet
      ref={sheet}
      footer={
        <View>
          <Text>My Foot-er is more awesome.</Text>
        </View>
      }
    >
      <View />
    </TrueSheet>
  )
}

Safe Area Handling

The footer owns the sheet's bottom edge, so it automatically absorbs the bottom safe-area inset as padding when insetAdjustment is "automatic" (the default). Your footer content stays above the home indicator while its background fills the inset — no manual padding needed.

const MyFooter = () => {
  return (
    <View style={{ height: 60, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Footer Content</Text>
    </View>
  );
};

// Usage
<TrueSheet detents={['auto']} footer={<MyFooter />} footerStyle={{ backgroundColor: '#333' }}>
  {/* content */}
</TrueSheet>

The inset is applied to the footer component itself, so set your background via footerStyle (or on your footer's root view) for it to fill the safe area.

When the keyboard opens, an absolute footer rises above it without a safe-area gap. With footerOptions.avoidKeyboard: false, it stays behind the keyboard and keeps its inset. A relative footer also keeps its inset. See Keyboard Handling.

On iPad, the sheet is displayed as a floating modal, so no inset is applied. Set insetAdjustment="never" to opt out entirely.

By default, the footer takes up space below the content and its height is included in the auto detent calculation. Set footerOptions.position to 'absolute' to float the footer over the content instead — it stays pinned to the bottom edge but no longer adds to the auto detent height. An absolute footer absorbs the bottom safe-area inset the same way a relative one does — see Safe Area Handling.

const App = () => {
  return (
    <TrueSheet
      detents={['auto']}
      scrollableRef={scrollableRef}
      footerOptions={{ position: 'absolute' }}
      footer={<Fab />}
    >
      <FlatList ref={scrollableRef} data={items} renderItem={({ item }) => <ItemRow item={item} />} />
    </TrueSheet>
  )
}

Since the footer overlaps the content, a plugged scrollableRef is padded by the footer's measured height automatically — the last item scrolls into view above the footer, and the footer counts toward the auto detent. See Footer Inset. For non-scrolling content, add bottom padding yourself so it ends above the footer.

A relative footer is laid out below the content — if your content is taller than the sheet's visible height (e.g. fixed detents), bound it with flex: 1 so the footer stays visible. Use 'absolute' if you want the footer to float regardless of the content's height.

An absolute footer's height counts toward the "peek" detent — collapse the sheet down to just the header, footer, and any peeking content.

const App = () => {
  return (
    <TrueSheet
      detents={['peek', 0.9]}
      initialDetentIndex={0}
      footer={<SheetActions />}
      footerOptions={{ position: 'absolute' }}
    >
      <BookingDetails />
    </TrueSheet>
  )
}

Since an absolute footer floats over the content, it stays visible at every detent. A relative footer is laid out below the content, so it's pushed off-screen at the peek detent and is excluded from the peek height. See Peeking Content for the full guide.

Edit on GitHub

On this page