or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animation-configuration.mdbottom-sheet-component.mdcontrol-hooks.mdgesture-event-handling.mdindex.mdmodal-components.mdscrollable-components.mdui-components.md
tile.json

modal-components.mddocs/

Modal Components

Modal bottom sheets that overlay the entire screen with stack management, presentation controls, and provider-based lifecycle management.

Capabilities

BottomSheetModal

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>
  );
};

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;

BottomSheetModalMethods

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>
  );
};

Stack Behaviors

Modal stack behaviors control how multiple modals interact:

  • push: Stack the new modal on top of existing ones
  • switch: Minimize current modal and show new one
  • replace: 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();
};

Modal Context Integration

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;
}