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

scrollable-components.mddocs/

Scrollable Components

Optimized scrollable components that integrate seamlessly with bottom sheet gestures, providing proper scroll coordination and interaction handling for various list types.

Capabilities

BottomSheetScrollView

ScrollView component optimized for bottom sheet with gesture coordination and proper scroll handling.

/**
 * ScrollView optimized for bottom sheet integration
 * @param props - ScrollView props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetScrollView: React.ForwardRefExoticComponent<BottomSheetScrollViewProps>;

interface BottomSheetScrollViewProps extends Omit<ScrollViewProps, 'decelerationRate' | 'scrollEventThrottle'>, BottomSheetScrollableProps {
  /** Child content for the scroll view */
  children: React.ReactNode | React.ReactNode[];
}

interface BottomSheetScrollViewMethods {
  /** Scroll to specific position */
  scrollTo(y?: number | {x?: number; y?: number; animated?: boolean}, x?: number, animated?: boolean): void;
  /** Scroll to end of content */
  scrollToEnd(options?: {animated: boolean}): void;
  /** Get scroll responder for advanced control */
  getScrollResponder(): ScrollResponderMixin;
  /** Get scrollable node reference */
  getScrollableNode(): any;
  /** Get inner view node reference */
  getInnerViewNode(): any;
  /** Set native props directly */
  setNativeProps(nativeProps: object): void;
}

Usage Examples:

import React, { useRef } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheetScrollView } from '@gorhom/bottom-sheet';

// Basic scroll view
const ScrollViewExample = () => {
  const scrollViewRef = useRef<BottomSheetScrollView>(null);

  const scrollToTop = () => {
    scrollViewRef.current?.scrollTo({ y: 0, animated: true });
  };

  return (
    <BottomSheetScrollView
      ref={scrollViewRef}
      contentContainerStyle={{ padding: 20 }}
    >
      <Text>Scrollable Content</Text>
      {Array.from({ length: 20 }).map((_, index) => (
        <View key={index} style={{ padding: 10, borderBottomWidth: 1 }}>
          <Text>Item {index + 1}</Text>
        </View>
      ))}
      <Button title="Scroll to Top" onPress={scrollToTop} />
    </BottomSheetScrollView>
  );
};

// With footer margin adjustment for animated footers
const ScrollViewWithFooter = () => {
  return (
    <BottomSheetScrollView
      enableFooterMarginAdjustment={true}
      contentContainerStyle={{ padding: 20 }}
    >
      <Text>Content that adjusts for animated footer</Text>
      {/* Content */}
    </BottomSheetScrollView>
  );
};

BottomSheetFlatList

FlatList component optimized for bottom sheet with proper virtualization and gesture coordination.

/**
 * FlatList optimized for bottom sheet integration
 * @param props - FlatList props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetFlatList: React.ForwardRefExoticComponent<BottomSheetFlatListProps<any>>;

interface BottomSheetFlatListProps<T> extends Omit<FlatListProps<T>, 'decelerationRate' | 'onScroll' | 'scrollEventThrottle'>, BottomSheetScrollableProps {}

interface BottomSheetFlatListMethods {
  /** Scroll to end of list */
  scrollToEnd(params?: {animated?: boolean | null}): void;
  /** Scroll to specific index */
  scrollToIndex(params: {animated?: boolean | null; index: number; viewOffset?: number; viewPosition?: number}): void;
  /** Scroll to specific item */
  scrollToItem(params: {animated?: boolean | null; item: any; viewPosition?: number}): void;
  /** Scroll to specific offset */
  scrollToOffset(params: {animated?: boolean | null; offset: number}): void;
  /** Record user interaction for performance */
  recordInteraction(): void;
  /** Flash scroll indicators */
  flashScrollIndicators(): void;
  /** Get scroll responder */
  getScrollResponder(): ScrollResponderMixin | null | undefined;
  /** Get native scroll reference */
  getNativeScrollRef(): RefObject<View> | RefObject<ScrollViewComponent> | null | undefined;
}

Usage Examples:

import React, { useRef, useMemo } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheetFlatList } from '@gorhom/bottom-sheet';

interface Item {
  id: string;
  title: string;
}

const FlatListExample = () => {
  const flatListRef = useRef<BottomSheetFlatList>(null);
  
  const data: Item[] = useMemo(() => 
    Array.from({ length: 100 }).map((_, index) => ({
      id: `item-${index}`,
      title: `Item ${index + 1}`,
    })), []
  );

  const renderItem = ({ item, index }: { item: Item; index: number }) => (
    <View style={{ padding: 15, borderBottomWidth: 1 }}>
      <Text>{item.title}</Text>
    </View>
  );

  const scrollToIndex = (index: number) => {
    flatListRef.current?.scrollToIndex({ index, animated: true });
  };

  const scrollToEnd = () => {
    flatListRef.current?.scrollToEnd({ animated: true });
  };

  return (
    <View style={{ flex: 1 }}>
      <View style={{ flexDirection: 'row', padding: 10 }}>
        <Button title="Scroll to Index 20" onPress={() => scrollToIndex(20)} />
        <Button title="Scroll to End" onPress={scrollToEnd} />
      </View>
      
      <BottomSheetFlatList
        ref={flatListRef}
        data={data}
        keyExtractor={(item) => item.id}
        renderItem={renderItem}
        contentContainerStyle={{ backgroundColor: 'white' }}
        enableFooterMarginAdjustment={true}
      />
    </View>
  );
};

// With pull-to-refresh
const FlatListWithRefresh = () => {
  const [data, setData] = React.useState<Item[]>([]);
  const [refreshing, setRefreshing] = React.useState(false);

  const onRefresh = async () => {
    setRefreshing(true);
    // Simulate data refresh
    await new Promise(resolve => setTimeout(resolve, 1000));
    setData(/* new data */);
    setRefreshing(false);
  };

  return (
    <BottomSheetFlatList
      data={data}
      renderItem={renderItem}
      refreshing={refreshing}
      onRefresh={onRefresh}
    />
  );
};

BottomSheetSectionList

SectionList component optimized for bottom sheet with section-based virtualization.

/**
 * SectionList optimized for bottom sheet integration
 * @param props - SectionList props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetSectionList: React.ForwardRefExoticComponent<BottomSheetSectionListProps<any, any>>;

interface BottomSheetSectionListProps<ItemT, SectionT> extends Omit<SectionListProps<ItemT, SectionT>, 'decelerationRate' | 'onScroll' | 'scrollEventThrottle'>, BottomSheetScrollableProps {}

interface BottomSheetSectionListMethods {
  /** Scroll to specific section and item */
  scrollToLocation(params: SectionListScrollParams): void;
  /** Record user interaction */
  recordInteraction(): void;
  /** Flash scroll indicators (iOS only) */
  flashScrollIndicators(): void;
  /** Get scroll responder */
  getScrollResponder(): ScrollResponderMixin | undefined;
  /** Get scrollable node */
  getScrollableNode(): NodeHandle | undefined;
}

interface SectionListScrollParams {
  animated?: boolean;
  itemIndex: number;
  sectionIndex: number;
  viewOffset?: number;
  viewPosition?: number;
}

Usage Example:

import React, { useRef } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheetSectionList } from '@gorhom/bottom-sheet';

interface Section {
  title: string;
  data: string[];
}

const SectionListExample = () => {
  const sectionListRef = useRef<BottomSheetSectionList>(null);
  
  const sections: Section[] = [
    { title: 'Fruits', data: ['Apple', 'Banana', 'Orange'] },
    { title: 'Vegetables', data: ['Carrot', 'Broccoli', 'Spinach'] },
    { title: 'Meat', data: ['Chicken', 'Beef', 'Pork'] },
  ];

  const renderItem = ({ item }: { item: string }) => (
    <View style={{ padding: 10, paddingLeft: 20 }}>
      <Text>{item}</Text>
    </View>
  );

  const renderSectionHeader = ({ section }: { section: Section }) => (
    <View style={{ padding: 10, backgroundColor: '#f0f0f0' }}>
      <Text style={{ fontWeight: 'bold' }}>{section.title}</Text>
    </View>
  );

  const scrollToLocation = () => {
    sectionListRef.current?.scrollToLocation({
      sectionIndex: 1,
      itemIndex: 0,
      animated: true,
    });
  };

  return (
    <View style={{ flex: 1 }}>
      <Button title="Scroll to Vegetables" onPress={scrollToLocation} />
      
      <BottomSheetSectionList
        ref={sectionListRef}
        sections={sections}
        keyExtractor={(item, index) => item + index}
        renderItem={renderItem}
        renderSectionHeader={renderSectionHeader}
        contentContainerStyle={{ backgroundColor: 'white' }}
      />
    </View>
  );
};

BottomSheetVirtualizedList

VirtualizedList component for advanced virtualization scenarios.

/**
 * VirtualizedList optimized for bottom sheet integration
 * @param props - VirtualizedList props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetVirtualizedList: React.ForwardRefExoticComponent<BottomSheetVirtualizedListProps<any>>;

interface BottomSheetVirtualizedListProps<T> extends Omit<VirtualizedListProps<T>, 'decelerationRate' | 'onScroll' | 'scrollEventThrottle'>, BottomSheetScrollableProps {}

interface BottomSheetVirtualizedListMethods {
  scrollToEnd(params?: {animated?: boolean}): void;
  scrollToIndex(params: {animated?: boolean; index: number; viewOffset?: number; viewPosition?: number}): void;
  scrollToItem(params: {animated?: boolean; item: any; viewPosition?: number}): void;
  scrollToOffset(params: {animated?: boolean; offset: number}): void;
  recordInteraction(): void;
}

BottomSheetFlashList

FlashList from @shopify/flash-list optimized for bottom sheet (requires peer dependency).

/**
 * FlashList optimized for bottom sheet integration
 * Requires @shopify/flash-list as peer dependency
 * @param props - FlashList props with bottom sheet enhancements
 * @returns JSX.Element
 */
declare const BottomSheetFlashList: React.ForwardRefExoticComponent<BottomSheetFlashListProps<any>>;

interface BottomSheetFlashListProps<T> extends Omit<FlashListProps<T>, 'decelerationRate' | 'onScroll' | 'scrollEventThrottle'>, BottomSheetScrollableProps {}

Usage Example:

// Install peer dependency: npm install @shopify/flash-list
import React from 'react';
import { View, Text } from 'react-native';
import { BottomSheetFlashList } from '@gorhom/bottom-sheet';

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

  const renderItem = ({ item }: { item: { id: number } }) => (
    <View style={{ height: 50, justifyContent: 'center', padding: 15 }}>
      <Text>Item {item.id}</Text>
    </View>
  );

  return (
    <BottomSheetFlashList
      data={data}
      renderItem={renderItem}
      estimatedItemSize={50}
      keyExtractor={(item) => item.id.toString()}
    />
  );
};

Common Scrollable Props

All bottom sheet scrollable components share these common props:

interface BottomSheetScrollableProps {
  /** Adjust margin for animated footer (default: false) */
  enableFooterMarginAdjustment?: boolean;
  /** Focus hook for React Navigation integration (default: useEffect) */
  focusHook?: (effect: EffectCallback, deps?: DependencyList) => void;
  /** ⚠️ Experimental: Custom scroll events handler hook */
  scrollEventsHandlersHook?: ScrollEventsHandlersHookType;
}

React Navigation Integration

Use useFocusEffect from React Navigation for proper focus management:

import { useFocusEffect } from '@react-navigation/native';
import { BottomSheetFlatList } from '@gorhom/bottom-sheet';

const NavigationExample = () => {
  return (
    <BottomSheetFlatList
      data={data}
      renderItem={renderItem}
      focusHook={useFocusEffect} // Use React Navigation's focus hook
    />
  );
};