Lynx/Modules/Bottom Sheet/API reference
@sigx/lynx-sheet · Beta · Component library

API reference#

Exports of @sigx/lynx-sheet v0.26.0.

Exports#

ExportKindPurpose
BottomSheetcomponentThe route-free bottom sheet.
BackdropcomponentThe dim behind the sheet.
BottomSheetProps / BottomSheetDragMode / BackdropProps / BackdropOptionstypesComponent contracts.
DetentSpec / DetentEnvtypesA rest position, and the environment it resolves against.
resolveDetentsfunctionResolve DetentSpec[] to px against the current viewport.
useSheetEnginehookSheet state + snap logic for a custom surface.
createSheetPanfunctionThe pan-gesture handler for a sheet.
decideDragOwnerfunctionSurface-drag arbitration — sheet or inner scroll.
SHEET_BACKDROP_MAX_OPACITY, GRABBER_HEIGHT, SNAP_MS, MIN_DISTANCE, …constantsThe engine's tuned values.
TSX
import { BottomSheet, Backdrop } from '@sigx/lynx-sheet';
import type { DetentSpec } from '@sigx/lynx-sheet';

useSheetHeight is not in this package — it reads the height of the navigation route sheet and lives in @sigx/lynx-navigation.

<BottomSheet> props#

Only detents is required.

Geometry#

PropTypeNotes
detentsreadonly DetentSpec[]Required. The resting heights. Re-resolved every render, never snapshotted — a composer floor that grows an attachment row re-seats the parked sheet automatically. The lowest resolved detent is the floor.
openDetentIndexnumberWhich detent open targets. Default: index 1 when there is more than one, else 0.
topOffsetnumberPx reserved above the fully-open sheet (top inset + a header it must never slide under). Caps every resolved detent.
bottomOffsetnumberPx the sheet's bottom edge sits above the true screen bottom — e.g. insets.bottom when an ancestor <SafeAreaView edges={['bottom']}> already pads the gesture bar. Without it the topOffset cap is measured from the wrong anchor and the open sheet slides under the header by exactly this amount.

Open state#

PropTypeNotes
openbooleanOpen ⇒ move to openDetentIndex; closed ⇒ the floor, or 0 when dismissible.
animatebooleanAnimate the open/close move. Default false — the sheet jumps instantly, so some other motion (a keyboard sliding away) reveals an already-painted sheet. User drags always animate their release snap.
dismissiblebooleanA release projecting below half the floor settles at reveal 0 and emits dismiss. The sheet only parks — the consumer flips open or unmounts it. Default false (persistent floor).

Dragging#

PropTypeNotes
dragMode'handle' | 'surface' | 'grabber' | 'none'What owns the gesture. Mount-constant — worklets register at setup. Default 'handle'.
grabberPxnumberHeight of the always-drags chrome strip at the top edge — the zone that claims the drag in 'surface', and the only zone that drags in 'grabber'. Meaningless for 'handle'/'none'. Mount-constant. Default 28.
dragEnabledbooleanGate the gesture (e.g. false while the keyboard owns the space). Default true.

Keyboard#

PropTypeNotes
liftSVSharedValue<number>External lift in px under the collapsed reveal — pass useKeyboardLiftSV() so the sheet rides above the keyboard. Effective reveal is max(reveal, floor + liftSV).
openToLiftbooleanOn open, snap to the current lifted position instead of the openDetentIndex detent. The live keyboard height is captured on the main thread the instant it opens, so when the lift animates to 0 the content does not move. Requires liftSV.

A sheet with liftSV cannot visually dismiss under an open keyboard — the lift wins the max. Don't pass one to a dismissible overlay sheet.

Backdrop and pinning#

PropTypeNotes
backdropboolean | BackdropOptionsDim behind the sheet. Default off.
pinnedBottomRefMainThreadRef<MainThread.Element | null>Element pinned to the sheet's visible bottom edge — a WhatsApp-style emoji category bar, a sticky action row. See Pinning to the visible edge.
onReveal(sv: SharedValue<number>) => voidReceives the combined reveal SharedValue once, at setup, so siblings can bind to it.

Events#

EventPayloadFires
snapnumberA drag settled. The payload indexes the snap candidates — the resolved detents normally, [floor, rest, top] under openToLift — so 0 is always the floor and the last index always the top. Only the latest release emits.
restnumberThe settled reveal in px — the sheet's visible height — on mount, open toggle, drag settle and dismiss. snap says which detent; rest says how tall.
dismissvoidThe sheet settled dismissed (drag or backdrop tap). The consumer closes it.
backdropTapvoidAny tap on the enabled backdrop, whether or not it dismisses.

Both snap and rest fire on the background thread.

Slots#

SlotNotes
defaultSheet body — laid out top-aligned in the fixed-height box.
handleDrag-handle region (a pill, a whole input row); rendered above default.

BackdropOptions#

TypeScript
interface BackdropOptions {
    /** Fully-open dim opacity. Default 0.4. */
    maxOpacity?: number;
    /** Tap on the dim dismisses (dismissible sheets only). Default true. */
    pressToDismiss?: boolean;
    /** Intrinsic tag to render the dim as, instead of 'view'. */
    guardTag?: string;
}

guardTag takes TOUCH_GUARD_TAG from @sigx/lynx-gestures ('sigx-touch-guard'), whose native view consumes the platform touch stream so an Android EditText underneath cannot steal focus. It is a plain string so lynx-sheet stays pure JS — the tag itself requires sigx prebuild.

Stacking#

Lynx has no z-index and no portal, so stacking is document order. The backdrop dims this component's positioned ancestor: for a full-screen dim, render the sheet as the last child of a full-surface positioned container. While the sheet is parked at its floor (or dismissed) the backdrop is display: none and intercepts nothing.

DetentSpec#

A rest position is a fraction of the screen, a fixed px height, or the keyboard. Resolution happens against live screen height, safe-area insets, the remembered keyboard height and topOffset — see resolveDetents, DEFAULT_DETENT_FRACTION and DEFAULT_KEYBOARD_FALLBACK_PX.