Skip to main content

Types

Core Types

BottomSheetStatus

Status of a bottom sheet.

type BottomSheetStatus = 'opening' | 'open' | 'closing' | 'hidden';
StatusDescription
openingSheet is animating open
openSheet is fully open
closingSheet is animating closed
hiddenSheet is hidden (used in switch mode)

OpenMode

Navigation mode when opening a sheet.

type OpenMode = 'push' | 'switch' | 'replace';
ModeDescription
pushStack new sheet on top
switchHide current, show new (restores on close)
replaceClose current, open new

BottomSheetState

The stable, public part of a sheet's state.

interface BottomSheetState {
id: string;
groupId: string;
status: BottomSheetStatus;
params?: Record<string, unknown>;
scaleBackground?: boolean;
keepMounted?: boolean;
}
Narrowed in 2.0

content, usePortal, portalSession and preventDismiss were removed from this type. They are store plumbing — read preventDismiss from useBottomSheetContext() instead.

PropertyTypeDescription
keepMountedbooleanWhen true, sheet stays in store after close (persistent mode)

Result Types

Both open() and close() report why they did nothing, rather than failing silently. See Close results for how to consume them.

OpenResult

Outcome of an open() call on the store.

type OpenResult =
| { opened: true; id: string }
| { opened: false; id: string; reason: OpenRejectionReason };

The public hooks project this down to the currency that is useful at each call site: useBottomSheetManager().open() returns string | null (the ID, or null), and useBottomSheetControl().open() returns boolean.


OpenRejectionReason

Why an open() call did not put the sheet on the stack. Each also logs a __DEV__ warning explaining which.

type OpenRejectionReason = 'already-active' | 'group-busy' | 'group-mismatch';
ReasonMeaning
already-activeThe sheet is already on the stack. Re-opening an active sheet is a no-op — close it first, or use updateParams()
group-busyAnother sheet in the same group is still animating open. Wait for it to settle (useBottomSheetStatus)
group-mismatchThe sheet is registered to a different manager group than the one opening it. A sheet belongs to the group that mounted it

CloseResult

Outcome of a close. Returned by close() on useBottomSheetManager, useBottomSheetControl and useBottomSheetContext.

type CloseResult =
| { closed: true }
| { closed: false; reason: CloseRejectionReason };

CloseRejectionReason

type CloseRejectionReason = 'blocked' | 'interceptor-error' | 'not-closable';
ReasonMeaning
blockedA useOnBeforeClose interceptor declined
interceptor-errorThe interceptor threw; the close is cancelled for safety
not-closableThere was nothing to close — already closing, hidden, or unknown sheet. Distinct from blocked: no interceptor had an opinion

CloseAllResult

Outcome of a cascading closeAll().

interface CloseAllResult {
/** Whether the whole requested range closed. */
completed: boolean;
/** IDs that closed, topmost first. */
closed: string[];
/** The sheet whose interceptor stopped the cascade, if one did. */
stoppedAt?: string;
}

A sheet with nothing to close does not stop the cascade — only a refusal does.


Adapter Types

SheetAdapterRef

The core adapter interface. Every adapter implements these two methods via useImperativeHandle.

interface SheetAdapterRef {
expand(): void; // Called by coordinator to show the sheet
close(): void; // Called by coordinator to hide the sheet
}

The coordinator calls expand() when the store status transitions to 'opening', and close() when status transitions to 'closing' or 'hidden'.


SheetAdapterEvents

Lifecycle events that adapters call back to the store. Returned by createSheetEventHandlers(sheetId).

interface SheetAdapterEvents {
handleDismiss(): void; // User-initiated dismiss (swipe, backdrop, back button)
handleOpened(): void; // Show animation completed — sheet is interactive
handleClosed(): void; // Hide animation completed — sheet is fully hidden
}

Event Flow:

  1. Coordinator calls ref.expand() → adapter shows UI
  2. Animation completes → adapter calls handleOpened()
  3. User swipes/taps backdrop → adapter calls handleDismiss()
  4. Hide animation completes → adapter calls handleClosed()

SheetRef

Ref type alias used in the refs registry.

type SheetRef = RefObject<SheetAdapterRef | null>;

Configuration Types

ScaleConfig

Configuration for scale animation.

interface ScaleConfig {
scale?: number; // Scale factor (default: 0.92)
translateY?: number; // Y translation in pixels (default: 10)
borderRadius?: number; // Border radius when scaled (default: 12)
animation?: ScaleAnimationConfig; // Animation config (default: timing 300ms)
}

ScaleAnimationConfig

Animation configuration for scale effect. Supports both timing and spring animations from Reanimated.

type ScaleAnimationConfig =
| { type: 'timing'; config?: WithTimingConfig }
| { type: 'spring'; config?: WithSpringConfig };

Examples:

// Timing animation (default)
const timingConfig: ScaleAnimationConfig = {
type: 'timing',
config: { duration: 300, easing: Easing.bezier(0.25, 0.1, 0.25, 1) },
};

// Spring animation
const springConfig: ScaleAnimationConfig = {
type: 'spring',
config: { damping: 15, stiffness: 150 },
};

BackdropConfig

What the manager's shared backdrop renders — a discriminated union, kind first. Set as the group default via backdrop on the provider, or per sheet via the backdrop prop on an adapter (false there disables the backdrop). See Backdrop.

type BackdropConfig =
| {
kind: 'styled';
style?: StyleProp<ViewStyle>; // merged over the group's style and the default rgba(0,0,0,0.5)
pressToDismiss?: boolean; // default: true
}
| {
kind: 'custom';
component: ComponentType<BackdropComponentProps>;
pressToDismiss?: boolean; // default: true
};

BackdropComponentProps

Props a kind: 'custom' backdrop component receives.

type BackdropComponentProps = {
sheetId: string;
/** -1 hidden → 0 fully visible (see HIDDEN_ANIMATED_INDEX). */
animatedIndex: SharedValue<number>;
/** Calls requestClose(sheetId) — onBeforeClose interceptors still run. */
close: () => void;
};

Portal Types

BottomSheetPortalRegistry

Interface to augment for type-safe portal IDs and params.

// In your project (e.g., src/types/bottom-sheet.d.ts)
import 'react-native-bottom-sheet-stack';

declare module 'react-native-bottom-sheet-stack' {
interface BottomSheetPortalRegistry {
'settings-sheet': true; // no params
'profile-sheet': { userId: string }; // with params
}
}
ValueMeaning
trueSheet has no params
{ ... }Sheet has required params

See Type-Safe Portal IDs for details.


BottomSheetPortalId

Type for portal sheet IDs.

// If BottomSheetPortalRegistry is augmented:
type BottomSheetPortalId = 'settings-sheet' | 'profile-sheet';

// If not augmented:
type BottomSheetPortalId = string;

BottomSheetPortalParams

Type helper to extract params for a given portal sheet ID.

// If registry defines: 'profile-sheet': { userId: string }
type Params = BottomSheetPortalParams<'profile-sheet'>;
// Result: { userId: string } | undefined

// If registry defines: 'settings-sheet': true
type Params = BottomSheetPortalParams<'settings-sheet'>;
// Result: undefined
undefined is always in the union

Even for a sheet with required params, the resolved type is T | undefinedresetParams() can clear params on an open sheet, so a sheet reading its own params can always find them missing. Under strict, read them optionally: params?.userId.


Hook Return Types

UseBottomSheetControlReturn

Return type of useBottomSheetControl hook.

interface UseBottomSheetControlReturn<T extends BottomSheetPortalId> {
/** `false` when the store declined — see OpenRejectionReason. */
open: OpenFunction<T>;
close: () => Promise<CloseResult>;
closeAll: (options?: CascadeOptions) => Promise<CloseAllResult>;
updateParams: (params: BottomSheetPortalParams<T>) => void;
resetParams: () => void;
}

UseBottomSheetContextReturn

Return type of useBottomSheetContext hook.

interface UseBottomSheetContextReturn<TParams> {
id: string;
params: TParams;
preventDismiss: boolean;
close: () => Promise<CloseResult>;
/** Closes every sheet above this one. `inclusive` closes this one too. */
closeAbove: (
options?: Omit<CascadeOptions, 'until'>
) => Promise<CloseAllResult>;
forceClose: () => void;
}

UseBottomSheetStatusReturn

Return type of useBottomSheetStatus hook.

interface UseBottomSheetStatusReturn {
status: BottomSheetStatus | null;
/** Fully open and interactive — not during the opening animation. */
isOpen: boolean;
isOpening: boolean;
isClosing: boolean;
/** On screen in any form: opening, open, or closing. */
isVisible: boolean;
}

Close Interception Types

OnBeforeCloseCallback

Callback type for useOnBeforeClose. Receives onConfirm and onCancel callbacks to call when the user makes a decision.

type OnBeforeCloseCallback = (context: {
onConfirm: () => void;
onCancel: () => void;
}) => void | boolean | Promise<boolean>;

Callback Pattern (Recommended):

  • Call onConfirm() to allow the close
  • Call onCancel() to block the close
  • Works seamlessly with Alert.alert and closeAll() cascade

Backward Compatible:

  • Return true — close proceeds
  • Return false — close is cancelled
  • Return Promise<boolean> — async confirmation

If the promise rejects, the close is cancelled for safety.


CascadeOptions

Options for closeAll() (available on both useBottomSheetManager and useBottomSheetControl), and for the bounded variants closeTo(), closeDepth() and closeAbove().

interface CascadeOptions {
/** Delay in ms between each close animation. Default: 100 */
stagger?: number;
/** Stop at this sheet rather than emptying the group. */
until?: string;
/** Whether the `until` sheet closes as well. Default: false */
inclusive?: boolean;
/** Close at most this many sheets, counting from the top. */
depth?: number;
}

until and depth both narrow the range, so with both set the one that closes fewer sheets wins — neither can widen past the other. An until that is not on the group's stack closes nothing rather than falling back to closing everything.