react-brain
Browse decisions
React & language foundations 3App architecture 11UI 13Platform & native 9Build, test, observe, secure 6AI in React apps 3stack composerdecision recordscensusstaleness benchnewsletterarchitecturechangelogmethodologyroadmap

entriesui · verified 2026-09-24 · react-native

Bottom sheets & modal sheets (React Native)

reviewedconfidence: mediumthis tier holds 71% on the public scorecard (7/20 graded · 0 overturned) →

related decisions: polish · nav

re-verified 3× — 2026-09-24 · 2026-08-18 · 2026-07-16 · changelog

recommendation

Default to a NATIVE sheet — react-native-true-sheet today — unless you need custom gesture choreography, where @gorhom/bottom-sheet remains the flexible JS incumbent. gorhom DRAWS a sheet in JS; the native libraries PRESENT the OS one, so detents, dismissal physics, screen-reader semantics and iOS 26 Liquid Glass come from the platform. Pin versions: the SWM line is 0.x and true-sheet ships every few days.

  • custom gesture-heavy sheet UIs (drag handoff to inner scroll, dynamic snap logic) → @gorhom/bottom-sheet
  • platform-authentic native sheet, stable today → react-native-true-sheet (3.11.x; New Architecture required — it is Fabric-only)
  • the sheet must hold a form or a text input → react-native-true-sheet (built-in keyboard handling and native a11y strings; in a JS-drawn sheet keyboard avoidance is yours to solve)
  • iPad / Android tablet layouts → react-native-true-sheet (side sheets; a phone-shaped bottom sheet stretched across a tablet is the giveaway of a JS-drawn one)
  • betting on the Software Mansion native line → @swmansion/react-native-bottom-sheet (0.x — pin versions, expect breaking changes)
  • the sheet is really a SCREEN (deep-linkable, own route) → react-native-screens FormSheet via native-stack (experimental — pin; see RB-E-NAV)

Options & tradeoffs

the field considered — and why each one isn’t the default here

optiontradeoffevidence
@gorhom/bottom-sheetThe JS incumbent: DRAWS a sheet on Reanimated (>=3.16 or 4) + Gesture Handler (>=2.16.1) rather than presenting the OS one; dynamic sizing, scroll handoff, most flexible for custom gesture-heavy sheets; ~9.1k stars, largest deployed base. 5.2.14 (2026-05-09, verified vs npm); see note: GORHOM MAINTENANCE.
@swmansion/react-native-bottom-sheetSoftware Mansion's native sheet components (inline AND modal, snap points; software-mansion-labs): platform-authentic behavior, peer RN >=0.76. Still 0.x — 0.16.2 latest, 0.17.0-next.2 on `next` (2026-09-24, verified vs npm) — pin, expect churn.
react-native-true-sheet (@lodev09)Native sheets on iOS, Android and web; the most complete native option (Fabric-only, native a11y, built-in keyboard handling, tablet side sheets, iOS 26+ Liquid Glass, Reanimated 4 interop, React Navigation sheet navigator). 3.11.14 (2026-09-09, verified vs npm); see note: TRUE-SHEET 4.0 LINE.203k/wk · ships in 1/14
react-native-screens FormSheetThe sheet as a NAVIGATION DESTINATION: native-stack presents a route as a form sheet (detents); still experimental on the 4.x line (4.28.0, 2026-09-14; 5.0.0-alpha.3 on `next`, verified vs npm) — RB-E-NAV owns it. true-sheet's sheet navigator covers the same case without waiting on the screens rewrite.

evidence: npm weekly downloads (signals snapshot) · “ships in n/D” = adoption across the production-app census, honest denominators

npm weekly downloads (from the corpus's last signals run): @gorhom/bottom-sheet 3.6M · @swmansion/react-native-bottom-sheet 651k · @lodev09/react-native-true-sheet 203k

Verified notes

The axis mirrors RB-E-POLISH's toasts: a JS-flexible incumbent vs platform-authentic native entrants. gorhom DRAWS a sheet with Reanimated + Gesture Handler, so every platform behavior (detents, dismissal physics, keyboard avoidance, screen-reader semantics, tablet layout, Liquid Glass) is re-implemented or missing; true-sheet and the SWM library PRESENT the OS sheet and inherit them. With true-sheet now the most complete native option and gorhom quiet since May, the JS incumbent is the specialist choice for custom gesture work, not the safe first pick. Medium confidence because adoption still lags the argument. GORHOM MAINTENANCE (2026-09-24, verified vs npm + the GitHub repo): 5.2.14 (2026-05-09) is still latest and the master branch has no commit since 2026-05-09; open issues are 48 (74 on 2026-08-18) → not abandoned, but no fix is shipping; a gorhom bug you hit is yours to patch. TRUE-SHEET 4.0 LINE (2026-09-24, verified vs npm): 3.11.x still gets patches (3.11.12–3.11.14, 2026-08-18 to 2026-09-09) while 4.0.0-beta.1 → beta.18 shipped between 2026-08-09 and 2026-09-23. Reanimated (>=4), worklets, React Navigation core (>=7) and Radix dialog peers are all optional (peerDependenciesMeta) → a Reanimated 3 app can adopt it without the interop. The 4.0 tripwire fires on the stable release. ADOPTION (2026-08-18, 34-app census): a sheet library in 7 of 14 RN apps — gorhom in 7, true-sheet in 1. That is what a recent inversion looks like. HISTORY: 2026-09-24 REOPENED: pins refreshed (true-sheet 3.11.14 + 4.0 beta.18, screens 4.28.0, SWM 0.17.0-next.2); gorhom open issues 74 → 48 with still no release or push since 2026-05-09; true-sheet's optional peers stated. 2026-08-18 CHALLENGED → OVERTURNED: default inverted from gorhom to true-sheet (true-sheet became the most complete native option; gorhom stopped shipping); graduated drafted → reviewed. 2026-07-16 GAP CLOSED: entry created by the TWiR #284–290 back-audit (SWM native sheet #284, true-sheet 3.11 #287, screens FormSheet #290; gorhom never covered).

Canonical reading

Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.

Building a drawer componentEmil Kowalski (Vaul author)

The design rationale under good sheets/drawers, from the author of web's canonical drawer (Vaul): velocity-based dismissal over distance thresholds, snap-point logic, scroll-vs-drag handoff, and background scaling — the interaction details that decide whether a sheet feels native. Web-authored, but it is the why-good-sheets-feel-good reference, exactly as this corpus uses his toast piece in RB-E-POLISH.

Sources

Depth (in-domain rules) is owned by the react-native-best-practices skill — this entry is selection breadth.

The full explanation

The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.

About bottom sheets & modal sheets (React Native)

Diataxis: Explanation. This page builds understanding of why the sheet decision is a decision at all, and why the recommendation now leans native. It is not an install guide or an API reference. Rendering-performance depth belongs to react-native-best-practices; keyboard behavior to RB-E-KEYBOARD; routing to RB-E-NAV; platform-feel in general to RB-E-NATIVE-UI. Read this for the why.

The one distinction that organises everything: drawing a sheet vs presenting one

There are two fundamentally different things a React Native library can do when you ask for a bottom sheet, and almost every difference between the options falls out of which one it does.

It can draw a sheet: a View positioned by animated values, with pan gestures wired to translate it, snap points implemented as numbers you supply, and a backdrop you also draw. That is @gorhom/bottom-sheet, built on Reanimated and Gesture Handler. Everything about the sheet is yours — which is exactly the appeal, and exactly the cost.

Or it can present one: hand the content to the platform and let the OS put it on screen — UISheetPresentationController on iOS, the Material bottom-sheet machinery on Android. That is react-native-true-sheet and @swmansion/react-native-bottom-sheet. You get the platform's detents, the platform's rubber-banding and dismissal physics, the platform's screen-reader semantics, and — on iOS 26 — the platform's Liquid Glass material, because none of it was re-implemented in the first place.

Everything below is a consequence of that split.

Why "just draw it" stops being free

A drawn sheet has to re-answer, in your code, questions the OS already answers:

  • Dismissal physics. Real sheets dismiss on velocity, not on distance crossed — a fast flick from near the top should dismiss, a slow drag past halfway should not. The reading in the index entry (Emil Kowalski, author of Vaul) is the canonical rationale for this and the related choices, and it is worth reading precisely because these are your decisions once you draw.
  • Scroll-vs-drag handoff. When the sheet contains a list, the gesture has to belong to the sheet until the list is at its top, and to the list after. Getting this subtly wrong is the most common way a sheet feels "off" without anyone being able to say why.
  • Accessibility semantics. A presented sheet arrives with a grabber label, detent state announcements and a dialog/pane role. A drawn one is a View until you say otherwise.
  • The keyboard. A sheet holding a TextInput has to move with the keyboard, on two platforms that animate the keyboard on different clocks (see RB-E-KEYBOARD). Native sheets inherit the platform's behavior; drawn sheets inherit your bug backlog.
  • Tablets. iPad and Android tablets expect a side sheet, not a phone-shaped sheet stretched across a tablet display. A phone-shaped sheet on a tablet is usually the visible signature of a drawn one.

None of that makes drawing wrong. It makes drawing a choice you should make deliberately, for sheets whose gesture behavior is genuinely custom.

Why the default inverted this month

When this entry was drafted (2026-07-16), @gorhom/bottom-sheet was the safe default and the native entrants were the interesting newcomers. A month of watching moved the line:

  • The native option grew up. react-native-true-sheet reached 3.11.14 (2026-09-09) while publishing every few days, and it is no longer the simpler option — it is the more complete one: Fabric-only by design, native accessibility strings, built-in keyboard handling, side sheets for iPad and Android tablets, iOS 26+ Liquid Glass, first-class Reanimated interop, and a sheet navigator for React Navigation. A 4.0 beta line is open (beta.18 on 2026-09-23), and its Reanimated 4, worklets and React Navigation peers are optional.
  • The incumbent went quiet. @gorhom/bottom-sheet sits at 5.2.14, published 2026-05-09, with no repository push since that date; open issues went from 74 (2026-08-18) to 48 (2026-09-24) without a release. It is not abandoned, and ~9.1k stars of deployed base do not evaporate — but "safe default" is a claim about maintenance as much as about features, and that claim is weaker than it was.

So the index entry now says: present by default, draw when you need custom choreography.

The third shape: a sheet that is really a screen

Some sheets are not components at all. If the sheet is deep-linkable, appears in the back stack, and owns its own data loading, it is a route that happens to be presented as a sheet.

Two paths exist. react-native-screens can present a native-stack route as a FormSheet with detents — still experimental on the 4.x line (4.28.0, 2026-09-14; a 5.0.0-alpha.3 line is open), so pin it. Or use react-native-true-sheet's sheet navigator, which reaches the same shape without waiting on the screens rewrite. The decision is not "which library" but "is this a component or a destination" — and answering that first usually settles the library question.

What the field looks like (and why confidence is medium, not high)

The 34-app census (2026-08-18) finds a sheet library in 7 of 14 React Native apps: @gorhom/bottom-sheet in 7 of them, react-native-true-sheet in 1. Adoption still points at the incumbent, which is what a recent inversion looks like — the argument moved before the ecosystem did. Two further reasons to hold this at medium confidence: @swmansion/react-native-bottom-sheet is still 0.x (0.16.2, with 0.17.0-next.2 on the next tag), and the option this entry now leads with has a major version in beta. Both are wired as tripwires in the index entry, so a stable 1.0 or 4.0 forces this page to be re-read rather than quietly aging.

How to read the recommendation

  1. Is this a destination or a component? Destination → sheet navigator or FormSheet route.
  2. Does the sheet need genuinely custom gesture behavior? Yes → @gorhom/bottom-sheet, and budget for the physics and handoff work as real work.
  3. Otherwise, present the OS sheet — react-native-true-sheet today (New Architecture required), @swmansion/react-native-bottom-sheet if you want to bet on the Software Mansion line and can absorb 0.x churn.
  4. Pin whichever you choose. Every native option here is pre-1.0 or shipping weekly.

Related in ui: styling · component-libs · animation · lists · a11y · i18n · charts · editors · svg · maps · calendars · polish