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

ui-components.mddocs/

UI Components

Specialized UI components including handles, backdrops, footers, and input components optimized for bottom sheet interactions with gesture coordination and proper styling integration.

Capabilities

BottomSheetHandle

Default handle component for dragging the sheet with customizable appearance and animated position feedback.

/**
 * Default handle component for bottom sheet
 * @param props - Handle props with animated values
 * @returns JSX.Element
 */
declare const BottomSheetHandle: React.FC<BottomSheetHandleProps>;

interface BottomSheetHandleProps extends BottomSheetVariables {
  /** Current sheet position index */
  animatedIndex: SharedValue<number>;
  /** Current sheet position in pixels */
  animatedPosition: SharedValue<number>;
}

interface BottomSheetDefaultHandleProps extends BottomSheetHandleProps {
  /** Handle container style */
  style?: ViewStyle;
  /** Handle indicator style */
  indicatorStyle?: ViewStyle;
  /** Content below the handle indicator */
  children?: React.ReactNode | React.ReactNode[];
}

Usage Examples:

import React from 'react';
import { View, Text } from 'react-native';
import BottomSheet, { BottomSheetHandle } from '@gorhom/bottom-sheet';

// Basic handle usage
const BasicHandleExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  return (
    <BottomSheet
      snapPoints={snapPoints}
      handleComponent={BottomSheetHandle}
    >
      <View style={{ flex: 1, padding: 20 }}>
        <Text>Content with default handle</Text>
      </View>
    </BottomSheet>
  );
};

// Custom handle styling
const StyledHandleExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderHandle = (props) => (
    <BottomSheetHandle
      {...props}
      style={{
        backgroundColor: '#f0f0f0',
        borderTopLeftRadius: 20,
        borderTopRightRadius: 20,
        paddingHorizontal: 20,
        paddingVertical: 10,
      }}
      indicatorStyle={{
        backgroundColor: '#007AFF',
        width: 50,
        height: 5,
      }}
    />
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      handleComponent={renderHandle}
    >
      <View style={{ flex: 1 }}>
        <Text>Content with styled handle</Text>
      </View>
    </BottomSheet>
  );
};

// Handle with additional content
const HandleWithContentExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderHandle = (props) => (
    <BottomSheetHandle
      {...props}
      style={{
        backgroundColor: 'white',
        borderTopWidth: 1,
        borderTopColor: '#e0e0e0',
        paddingBottom: 10,
      }}
    >
      <View style={{ alignItems: 'center', paddingTop: 10 }}>
        <Text style={{ fontSize: 16, fontWeight: 'bold' }}>
          Pull to expand
        </Text>
      </View>
    </BottomSheetHandle>
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      handleComponent={renderHandle}
    >
      <View style={{ flex: 1 }}>
        <Text>Handle with custom content</Text>
      </View>
    </BottomSheet>
  );
};

BottomSheetBackdrop

Backdrop component that appears behind the sheet with configurable opacity, appearance behavior, and touch handling.

/**
 * Backdrop component for bottom sheet
 * @param props - Backdrop props with animated values and styling
 * @returns JSX.Element
 */
declare const BottomSheetBackdrop: React.FC<BottomSheetBackdropProps>;

interface BottomSheetBackdropProps extends BottomSheetVariables {
  /** Backdrop style */
  style?: ViewStyle;
  /** Current sheet position index */
  animatedIndex: SharedValue<number>;
  /** Current sheet position in pixels */
  animatedPosition: SharedValue<number>;
}

interface BottomSheetDefaultBackdropProps extends BottomSheetBackdropProps {
  /** Maximum backdrop opacity (default: 0.5) */
  opacity?: number;
  /** Index when backdrop appears (default: 1) */
  appearsOnIndex?: number;
  /** Index when backdrop disappears (default: 0) */
  disappearsOnIndex?: number;
  /** Enable touch through backdrop (default: false) */
  enableTouchThrough?: boolean;
  /** Press behavior: 'none' | 'close' | 'collapse' | number (default: 'close') */
  pressBehavior?: 'none' | 'close' | 'collapse' | number;
  /** Custom press callback */
  onPress?: () => void;
  /** Child content for custom backdrop content */
  children?: React.ReactNode | React.ReactNode[];
}

Usage Examples:

import React from 'react';
import { View, Text } from 'react-native';
import BottomSheet, { BottomSheetBackdrop } from '@gorhom/bottom-sheet';

// Basic backdrop usage
const BasicBackdropExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderBackdrop = (props) => (
    <BottomSheetBackdrop
      {...props}
      disappearsOnIndex={-1}
      appearsOnIndex={0}
    />
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      backdropComponent={renderBackdrop}
    >
      <View style={{ flex: 1, padding: 20 }}>
        <Text>Content with basic backdrop</Text>
      </View>
    </BottomSheet>
  );
};

// Custom backdrop behavior
const CustomBackdropExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderBackdrop = (props) => (
    <BottomSheetBackdrop
      {...props}
      opacity={0.8}
      appearsOnIndex={1} // Only show backdrop from index 1
      disappearsOnIndex={0}
      pressBehavior="collapse" // Collapse instead of close
      style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
    />
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      backdropComponent={renderBackdrop}
    >
      <View style={{ flex: 1 }}>
        <Text>Custom backdrop behavior</Text>
      </View>
    </BottomSheet>
  );
};

// Backdrop with custom press handling
const InteractiveBackdropExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderBackdrop = (props) => (
    <BottomSheetBackdrop
      {...props}
      opacity={0.6}
      pressBehavior="none" // Disable default behavior
      onPress={() => {
        console.log('Custom backdrop press');
        // Custom logic here
      }}
    />
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      backdropComponent={renderBackdrop}
    >
      <View style={{ flex: 1 }}>
        <Text>Backdrop with custom press handling</Text>
      </View>
    </BottomSheet>
  );
};

// Backdrop that snaps to specific index
const SnapBackdropExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderBackdrop = (props) => (
    <BottomSheetBackdrop
      {...props}
      pressBehavior={1} // Snap to index 1 when pressed
    />
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      backdropComponent={renderBackdrop}
    >
      <View style={{ flex: 1 }}>
        <Text>Backdrop snaps to index 1</Text>
      </View>
    </BottomSheet>
  );
};

BottomSheetTextInput

TextInput component optimized for bottom sheet keyboard handling with automatic keyboard behavior coordination.

/**
 * TextInput optimized for bottom sheet keyboard handling
 * @param props - Standard TextInput props with internal optimizations
 * @returns JSX.Element
 */
declare const BottomSheetTextInput: React.ForwardRefExoticComponent<BottomSheetTextInputProps>;

interface BottomSheetTextInputProps extends TextInputProps {
  // Inherits all standard TextInput props
  // No additional props - optimized internally for keyboard behavior
}

Usage Examples:

import React, { useState } from 'react';
import { View, Text } from 'react-native';
import BottomSheet, { BottomSheetTextInput } from '@gorhom/bottom-sheet';

// Basic text input usage
const TextInputExample = () => {
  const [text, setText] = useState('');
  const snapPoints = useMemo(() => ['25%', '50%', '90%'], []);

  return (
    <BottomSheet
      snapPoints={snapPoints}
      keyboardBehavior="interactive"
      keyboardBlurBehavior="restore"
    >
      <View style={{ flex: 1, padding: 20 }}>
        <Text>Enter your message:</Text>
        <BottomSheetTextInput
          value={text}
          onChangeText={setText}
          placeholder="Type here..."
          style={{
            marginTop: 10,
            padding: 15,
            backgroundColor: '#f0f0f0',
            borderRadius: 8,
          }}
        />
      </View>
    </BottomSheet>
  );
};

// Multiple text inputs
const MultiInputExample = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [message, setMessage] = useState('');
  const snapPoints = useMemo(() => ['40%', '70%', '95%'], []);

  return (
    <BottomSheet
      snapPoints={snapPoints}
      keyboardBehavior="extend"
      enableBlurKeyboardOnGesture={true}
    >
      <View style={{ flex: 1, padding: 20 }}>
        <Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 20 }}>
          Contact Form
        </Text>
        
        <Text>Name:</Text>
        <BottomSheetTextInput
          value={name}
          onChangeText={setName}
          placeholder="Your name"
          style={inputStyle}
        />
        
        <Text style={{ marginTop: 15 }}>Email:</Text>
        <BottomSheetTextInput
          value={email}
          onChangeText={setEmail}
          placeholder="your@email.com"
          keyboardType="email-address"
          style={inputStyle}
        />
        
        <Text style={{ marginTop: 15 }}>Message:</Text>
        <BottomSheetTextInput
          value={message}
          onChangeText={setMessage}
          placeholder="Your message"
          multiline
          numberOfLines={4}
          style={[inputStyle, { height: 100, textAlignVertical: 'top' }]}
        />
      </View>
    </BottomSheet>
  );
};

const inputStyle = {
  marginTop: 5,
  padding: 15,
  backgroundColor: '#f8f8f8',
  borderRadius: 8,
  borderWidth: 1,
  borderColor: '#e0e0e0',
};

// Text input with validation
const ValidatedInputExample = () => {
  const [email, setEmail] = useState('');
  const [isValid, setIsValid] = useState(true);
  const snapPoints = useMemo(() => ['50%', '80%'], []);

  const validateEmail = (text: string) => {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const valid = emailRegex.test(text);
    setIsValid(valid);
    setEmail(text);
  };

  return (
    <BottomSheet snapPoints={snapPoints}>
      <View style={{ flex: 1, padding: 20 }}>
        <Text>Email Address:</Text>
        <BottomSheetTextInput
          value={email}
          onChangeText={validateEmail}
          placeholder="Enter your email"
          keyboardType="email-address"
          style={[
            inputStyle,
            !isValid && { borderColor: 'red', borderWidth: 2 }
          ]}
        />
        {!isValid && (
          <Text style={{ color: 'red', marginTop: 5 }}>
            Please enter a valid email address
          </Text>
        )}
      </View>
    </BottomSheet>
  );
};

BottomSheetView

Basic view component optimized for bottom sheet with footer margin adjustment and focus management.

/**
 * View component optimized for bottom sheet
 * @param props - View props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetView: React.ForwardRefExoticComponent<BottomSheetViewProps>;

interface BottomSheetViewProps extends ViewProps {
  /** Adjust margin for animated footer (default: false) */
  enableFooterMarginAdjustment?: boolean;
  /** Focus hook for React Navigation integration (default: useEffect) */
  focusHook?: (effect: EffectCallback, deps?: DependencyList) => void;
  /** Child content */
  children: React.ReactNode | React.ReactNode[];
}

Usage Examples:

import React from 'react';
import { Text } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';

// Basic view usage
const BasicViewExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  return (
    <BottomSheet snapPoints={snapPoints}>
      <BottomSheetView style={{ flex: 1, padding: 20 }}>
        <Text>Basic bottom sheet view content</Text>
      </BottomSheetView>
    </BottomSheet>
  );
};

// View with footer margin adjustment
const ViewWithFooterExample = () => {
  const snapPoints = useMemo(() => ['40%', '70%'], []);

  return (
    <BottomSheet
      snapPoints={snapPoints}
      footerComponent={CustomFooter}
    >
      <BottomSheetView
        enableFooterMarginAdjustment={true}
        style={{ flex: 1, padding: 20 }}
      >
        <Text>Content that adjusts for animated footer</Text>
        {/* More content */}
      </BottomSheetView>
    </BottomSheet>
  );
};

// View with React Navigation integration
const NavigationViewExample = () => {
  const snapPoints = useMemo(() => ['50%', '80%'], []);

  return (
    <BottomSheet snapPoints={snapPoints}>
      <BottomSheetView
        focusHook={useFocusEffect} // Use React Navigation focus hook
        style={{ flex: 1, padding: 20 }}
      >
        <Text>View that properly handles navigation focus</Text>
      </BottomSheetView>
    </BottomSheet>
  );
};

BottomSheetDraggableView

View component that enables dragging behavior for custom draggable areas.

/**
 * View component that enables dragging behavior
 * @param props - View props with gesture references
 * @returns JSX.Element
 */
declare const BottomSheetDraggableView: React.ForwardRefExoticComponent<BottomSheetDraggableViewProps>;

interface BottomSheetDraggableViewProps extends ViewProps {
  /** Native gesture reference for coordination */
  nativeGestureRef?: Exclude<GestureRef, number>;
  /** Refresh control gesture reference */
  refreshControlGestureRef?: Exclude<GestureRef, number>;
  /** Child content */
  children: React.ReactNode | React.ReactNode[];
}

Usage Example:

import React from 'react';
import { View, Text } from 'react-native';
import BottomSheet, { BottomSheetDraggableView } from '@gorhom/bottom-sheet';

const DraggableViewExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  return (
    <BottomSheet snapPoints={snapPoints}>
      <View style={{ flex: 1 }}>
        <BottomSheetDraggableView
          style={{
            backgroundColor: '#f0f0f0',
            padding: 20,
            marginBottom: 10,
          }}
        >
          <Text>This area can be dragged to move the sheet</Text>
        </BottomSheetDraggableView>
        
        <View style={{ flex: 1, padding: 20 }}>
          <Text>Regular content area</Text>
        </View>
      </View>
    </BottomSheet>
  );
};

Footer Components

Footer components that stick to the bottom of the sheet with automatic positioning.

/**
 * Footer component that sticks to bottom of sheet
 * @param props - Footer props with animated position
 * @returns JSX.Element
 */
declare const BottomSheetFooter: React.FC<BottomSheetFooterProps>;
declare const BottomSheetFooterContainer: React.FC<BottomSheetDefaultFooterProps>;

interface BottomSheetFooterProps {
  /** Calculated footer position (required) */
  animatedFooterPosition: SharedValue<number>;
}

interface BottomSheetDefaultFooterProps extends BottomSheetFooterProps {
  /** Bottom safe area inset (default: 0) */
  bottomInset?: number;
  /** Container style */
  style?: ViewStyle;
  /** Footer content */
  children?: React.ReactNode | React.ReactNode[];
}

Usage Example:

import React from 'react';
import { View, Text, Button } from 'react-native';
import BottomSheet, { 
  BottomSheetFooter, 
  BottomSheetView 
} from '@gorhom/bottom-sheet';

const FooterExample = () => {
  const snapPoints = useMemo(() => ['25%', '50%', '75%'], []);

  const renderFooter = (props) => (
    <BottomSheetFooter
      {...props}
      bottomInset={20}
      style={{
        backgroundColor: 'white',
        borderTopWidth: 1,
        borderTopColor: '#e0e0e0',
        padding: 20,
      }}
    >
      <Button title="Action Button" onPress={() => {}} />
    </BottomSheetFooter>
  );

  return (
    <BottomSheet
      snapPoints={snapPoints}
      footerComponent={renderFooter}
    >
      <BottomSheetView
        enableFooterMarginAdjustment={true}
        style={{ flex: 1, padding: 20 }}
      >
        <Text>Content with footer</Text>
      </BottomSheetView>
    </BottomSheet>
  );
};

Touchable Components

Touchable components optimized for bottom sheet gesture handling:

/** TouchableHighlight optimized for bottom sheet */
declare const TouchableHighlight: React.ComponentType<TouchableHighlightProps>;

/** TouchableOpacity optimized for bottom sheet */
declare const TouchableOpacity: React.ComponentType<TouchableOpacityProps>;

/** TouchableWithoutFeedback optimized for bottom sheet */
declare const TouchableWithoutFeedback: React.ComponentType<TouchableWithoutFeedbackProps>;

Usage Example:

import React from 'react';
import { View, Text } from 'react-native';
import BottomSheet, { TouchableOpacity } from '@gorhom/bottom-sheet';

const TouchableExample = () => {
  return (
    <BottomSheet snapPoints={['50%']}>
      <View style={{ flex: 1, padding: 20 }}>
        <TouchableOpacity
          style={{
            backgroundColor: '#007AFF',
            padding: 15,
            borderRadius: 8,
            alignItems: 'center',
          }}
          onPress={() => console.log('Button pressed')}
        >
          <Text style={{ color: 'white', fontWeight: 'bold' }}>
            Optimized Button
          </Text>
        </TouchableOpacity>
      </View>
    </BottomSheet>
  );
};

Utility Functions

createBottomSheetScrollableComponent

Factory function for creating custom scrollable components compatible with bottom sheet integration.

/**
 * Factory function for creating custom scrollable components
 * @param type - Type of scrollable component from SCROLLABLE_TYPE enum
 * @param ScrollableComponent - The base scrollable component to enhance
 * @returns Enhanced scrollable component with bottom sheet integration
 */
declare function createBottomSheetScrollableComponent<T, P>(
  type: SCROLLABLE_TYPE,
  ScrollableComponent: React.ComponentType<P>
): React.ForwardRefExoticComponent<P>;

enum SCROLLABLE_TYPE {
  UNDETERMINED = 0,
  VIEW = 1,
  FLATLIST = 2,
  SCROLLVIEW = 3,
  SECTIONLIST = 4,
  VIRTUALIZEDLIST = 5,
}

Usage Example:

import React from 'react';
import { FlatList } from 'react-native';
import { createBottomSheetScrollableComponent, SCROLLABLE_TYPE } from '@gorhom/bottom-sheet';

// Create custom enhanced FlatList
const CustomBottomSheetFlatList = createBottomSheetScrollableComponent(
  SCROLLABLE_TYPE.FLATLIST,
  FlatList
);

const CustomScrollableExample = () => {
  const data = Array.from({ length: 100 }).map((_, index) => ({ id: index }));

  return (
    <CustomBottomSheetFlatList
      data={data}
      renderItem={({ item }) => (
        <View style={{ padding: 15 }}>
          <Text>Item {item.id}</Text>
        </View>
      )}
      keyExtractor={(item) => item.id.toString()}
    />
  );
};