A performant interactive bottom sheet with fully configurable options for React Native applications.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Modal bottom sheets that overlay the entire screen with stack management, presentation controls, and provider-based lifecycle management.
Modal version of the bottom sheet that overlays the entire screen and supports data passing and stack behaviors.
/**
* Modal bottom sheet component that overlays the entire screen
* @param props - Modal configuration props extending BottomSheetProps
* @returns JSX.Element
*/
declare const BottomSheetModal: React.ForwardRefExoticComponent<BottomSheetModalProps>;
interface BottomSheetModalProps<T = any> extends Omit<BottomSheetProps, 'containerHeight' | 'onClose'> {
/** Modal identifier for stack management (default: auto-generated) */
name?: string;
/** Stack behavior when mounting: 'push' | 'switch' | 'replace' (default: 'switch') */
stackBehavior?: 'push' | 'switch' | 'replace';
/** Auto-dismiss modal when sheet closes (default: true) */
enableDismissOnClose?: boolean;
/** Custom container component for modal content */
containerComponent?: React.ComponentType<React.PropsWithChildren>;
/** Callback when modal is dismissed */
onDismiss?: () => void;
/** Content with optional data passing support */
children: React.FC<{ data?: T }> | React.ReactNode[] | React.ReactNode;
}Usage Examples:
import React, { useRef } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheetModal, BottomSheetModalProvider } from '@gorhom/bottom-sheet';
// Basic modal
const ModalExample = () => {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);
const handlePresentModal = () => {
bottomSheetModalRef.current?.present();
};
const handleDismissModal = () => {
bottomSheetModalRef.current?.dismiss();
};
return (
<BottomSheetModalProvider>
<View style={{ flex: 1, padding: 24 }}>
<Button title="Present Modal" onPress={handlePresentModal} />
<BottomSheetModal
ref={bottomSheetModalRef}
index={1}
snapPoints={snapPoints}
onDismiss={() => console.log('Modal dismissed')}
>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text>Modal Content</Text>
<Button title="Dismiss" onPress={handleDismissModal} />
</View>
</BottomSheetModal>
</View>
</BottomSheetModalProvider>
);
};
// With data passing
interface UserData {
id: number;
name: string;
email: string;
}
const DataPassingExample = () => {
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ['40%', '75%'], []);
const handlePresentModal = () => {
const userData: UserData = {
id: 1,
name: 'John Doe',
email: 'john@example.com'
};
bottomSheetModalRef.current?.present(userData);
};
return (
<BottomSheetModalProvider>
<View style={{ flex: 1, padding: 24 }}>
<Button title="Show User Details" onPress={handlePresentModal} />
<BottomSheetModal
ref={bottomSheetModalRef}
index={0}
snapPoints={snapPoints}
enableDismissOnClose={true}
>
{({ data }: { data?: UserData }) => (
<View style={{ flex: 1, padding: 20 }}>
<Text>User Details</Text>
{data && (
<>
<Text>ID: {data.id}</Text>
<Text>Name: {data.name}</Text>
<Text>Email: {data.email}</Text>
</>
)}
</View>
)}
</BottomSheetModal>
</View>
</BottomSheetModalProvider>
);
};
// Stack behavior example
const StackBehaviorExample = () => {
const modal1Ref = useRef<BottomSheetModal>(null);
const modal2Ref = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ['50%'], []);
return (
<BottomSheetModalProvider>
<View style={{ flex: 1, padding: 24 }}>
<Button title="Show Modal 1" onPress={() => modal1Ref.current?.present()} />
{/* First modal with push behavior */}
<BottomSheetModal
ref={modal1Ref}
index={0}
snapPoints={snapPoints}
stackBehavior="push"
name="modal1"
>
<View style={{ flex: 1, padding: 20 }}>
<Text>Modal 1</Text>
<Button
title="Show Modal 2 (Replace)"
onPress={() => modal2Ref.current?.present()}
/>
</View>
</BottomSheetModal>
{/* Second modal with replace behavior */}
<BottomSheetModal
ref={modal2Ref}
index={0}
snapPoints={snapPoints}
stackBehavior="replace"
name="modal2"
>
<View style={{ flex: 1, padding: 20 }}>
<Text>Modal 2 (Replaced Modal 1)</Text>
</View>
</BottomSheetModal>
</View>
</BottomSheetModalProvider>
);
};Provider component that manages modal bottom sheets lifecycle and stack behavior. Must wrap components that use BottomSheetModal.
/**
* Provider for managing modal bottom sheets
* @param props - Provider props with children
* @returns JSX.Element
*/
declare const BottomSheetModalProvider: React.FC<BottomSheetModalProviderProps>;
interface BottomSheetModalProviderProps {
/** Child components that may contain BottomSheetModal components */
children?: React.ReactNode;
}Usage Example:
import React from 'react';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import App from './App';
// Wrap your app or screen components
const AppWithProvider = () => {
return (
<BottomSheetModalProvider>
<App />
</BottomSheetModalProvider>
);
};
export default AppWithProvider;Interface for imperative modal methods available through refs.
interface BottomSheetModalMethods<T = any> extends BottomSheetMethods {
/** Present the modal to the initial snap point with optional data */
present: (data?: T) => void;
/** Close and unmount the modal */
dismiss: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
}Usage with Ref:
import React, { useRef } from 'react';
import { BottomSheetModal } from '@gorhom/bottom-sheet';
const ComponentWithModalRef = () => {
const modalRef = useRef<BottomSheetModal>(null);
const handleOpenModal = () => {
// Present modal
modalRef.current?.present();
};
const handleCloseModal = () => {
// Dismiss modal with animation
modalRef.current?.dismiss();
};
const handleSnapToIndex = () => {
// Use inherited BottomSheetMethods
modalRef.current?.snapToIndex(1);
};
return (
<BottomSheetModal ref={modalRef} snapPoints={['50%', '90%']}>
{/* Modal content */}
</BottomSheetModal>
);
};Modal stack behaviors control how multiple modals interact:
push: Stack the new modal on top of existing onesswitch: Minimize current modal and show new onereplace: Dismiss current modal and show new one (default)// Example showing different stack behaviors
const handlePresentPushModal = () => {
// Keeps current modal and stacks new one
pushModalRef.current?.present();
};
const handlePresentSwitchModal = () => {
// Minimizes current modal and shows new one
switchModalRef.current?.present();
};
const handlePresentReplaceModal = () => {
// Dismisses current modal and shows new one
replaceModalRef.current?.present();
};The modal system provides context for managing multiple modals:
interface BottomSheetModalContextType {
/** Dismiss a specific modal by key */
dismiss: (key?: string) => boolean;
/** Dismiss all modals */
dismissAll: () => void;
}