breffy-react-native-bottom-sheet
breffy-react-native-bottom-sheet copied to clipboard
Blazingly performant interactive bottom sheet with snap points support powered by Reanimated 2 :star2: :tada:
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
- Features
- Installation
-
Usage
- Custom Handle
- React Navigation Integration
- Touchables
- Props
- Methods
- Hooks
-
Scrollables
- BottomSheetFlatList
- BottomSheetSectionList
- BottomSheetScrollView
- BottomSheetView
- To Do
- FAQ
- Credits
- 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 ❤️
- react-native-reanimated
- react-native-gesture-handler
- react-native-redash
- @react-native-community/bob
License
Apache-2.0