breffy-react-native-bottom-sheet icon indicating copy to clipboard operation
breffy-react-native-bottom-sheet copied to clipboard

Blazingly performant interactive bottom sheet with snap points support powered by Reanimated 2 :star2: :tada:

React Native Bottom Sheet

npm npm npm

A performant interactive bottom sheet with fully configurable options 🚀

Initially, this project was a cloned of react-native-bottom-sheet by @gorhom ❤️. However, it is been fully re-written to add extra functionalities and simplify the approach.


Table of Contents

  1. Features
  2. Installation
  3. Usage
    • Custom Handle
    • React Navigation Integration
    • Touchables
  4. Props
  5. Methods
  6. Hooks
  7. Scrollables
    • BottomSheetFlatList
    • BottomSheetSectionList
    • BottomSheetScrollView
    • BottomSheetView
  8. To Do
  9. FAQ
  10. Credits
  11. License

Features

  • Smooth interactions & snapping animations.
  • Support FlatList, SectionList, ScrollView & View scrolling interactions.
  • Support React Navigation Integration.
  • Compatible with Reanimated v1 & v2.
  • Compatible with Expo.
  • Written in TypeScript.

Installation

yarn add @breeffy/react-native-bottom-sheet
# or
npm install @breeffy/react-native-bottom-sheet

⚠️ You need to install react-native-reanimated v2 & react-native-gesture-handler and follow their installation instructions.

Usage

import React, { useCallback, useMemo, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { BottomSheet, SnapPoint } from '@breeffy/react-native-bottom-sheet';

const App = () => {
  // hooks
  const bottomSheetRef = useRef<BottomSheet>(null);

  // variables
  const snapPoints = useMemo<SnapPoint[]>(
    () => [
      { relativeTo: 'content', percentagesOf: 30 },
      { relativeTo: 'content', percentagesOf: 70 },
      { relativeTo: 'content', percentagesOf: 100 }
    ],
    []
  );

  // callbacks
  const handleSheetChanges = useCallback((index: number) => {
    console.log('handleSheetChanges', index);
  }, []);

  // renders
  return (
    <View style={styles.container}>
      <BottomSheet
        ref={bottomSheetRef}
        initialSnapIndex={1}
        snapPoints={snapPoints}
        onChange={handleSheetChanges}
      >
        {/* INSERT A SCROLLABLE HERE */}
      </BottomSheet>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24
  }
});

export default App;

Props

initialSnapIndex

Initial snap index. You also could provide {-1} to initiate bottom sheet in closed state.

required: NO | type: number | default: 0

snapPoints

Points for the bottom sheet to snap to, points should be sorted from bottom to top. It accepts array of number, string or mix. String values should be a percentage.

required: YES | type: SnapPoint[]
example: [{ relativeTo: 'window', percentagesOf: 10 },{ relativeTo: 'content', percentagesOf: 70 }, { relativeTo: 'content', percentagesOf: 100 }]

topInset

Top inset value helps to calculate percentage snap points values. usually comes from @react-navigation/stack hook useHeaderHeight or from react-native-safe-area-context hook useSafeArea.

required: NO | type: number | default: 0

animationDuration

Snapping animation duration.

required: NO | type: number | default: 500

animationEasing

Snapping animation easing function.

required: NO | type: Animated.EasingFunction | default: Easing.out(Easing.back(0.75))

animatedPosition

Animated shared value to be used as a callback for the position node internally.

required: NO | type: Animated.SharedValue

animatedPositionIndex

Animated shared value to be used as a callback for the position index node internally.

required: NO | type: Animated.SharedValue

handleComponent

Component to be placed as a sheet handle.

required: NO | type: () => JSX.Element

backgroundComponent

Component to be placed as a background.

required: NO | type: React.FC<ViewProps>

onlyDistinctSnaps

Determine will onChange() and onAnimate() callbacks be called if animating to the same snap point.

required: NO | type: boolean | default: true

onAnimate

Callback when the sheet about to animate to a new position.

required: NO | type: (fromIndex: number, toIndex: number) => void

onChange

Callback when sheet position changed to a provided point.

required: NO | type: (index: number) => void

children

A scrollable node or normal view.

required: YES | type: () => React.ReactNode | React.ReactNode[] | React.ReactNode

Methods

snapTo

Snap to one of the provided points from snapPoints.

type: (index: number) => void

expand

Snap to the maximum provided point from snapPoints.

type: () => void

collapse

Snap to the minimum provided point from snapPoints.

type: () => void

close

Close the bottom sheet.

type: () => void

Hooks

useBottomSheet

The library provide useBottomSheet hook to provide the bottom sheet methods, anywhere inside the sheet content.

type: BottomSheetMethods

Scrollables

This library provides a pre-integrated views that utilise an internal functionalities with the bottom sheet to allow smooth interactions. These views i called them Scrollables and they are:

  • BottomSheetFlatList
  • BottomSheetSectionList
  • BottomSheetScrollView
  • BottomSheetView

To Do

  • [ ] Add tablets support.
  • [x] Add Reanimated v2 support.

FAQ

How this library differ from reanimated-bottom-sheet or react-native-scroll-bottom-sheet?

This library was built to provide the most native-like experience and could fit any use-case that developers wants it to be.

While both libraries providing similar experience, but they still missing the following:

  • reanimated-bottom-sheet
    • Seamless gesture interaction between the sheet and the content.
  • react-native-scroll-bottom-sheet
    • Extracting scrollable content to allow developers customize the sheet content, like integrate React Navigation as the sheet content.

Both libraries are great! and I have used both of them at my work ❤️

How can I integrate React Navigation?

here you go React Navigation Integration :)

Will this library support Reanimated v2?

Yes 🎉

Built With ❤️

License

Apache-2.0

Liked the library? 😇

Buy Me A Coffee