The smart ๐, tiny ๐ฆ, and flexible ๐ bottom sheet your app craves ๐
- ๐ฆ Very tiny and lightweight
- 0๏ธโฃ No dependency (yeah!, just plug and play ๐)
- โจ Modal and standard (non-modal) bottom sheet support
- โจ Smart & automatic keyboard and orientation handling for iOS & Android
- ๐ช Imperative calls
- ๐ Supports FlatList, SectionList, ScrollView & View scrolling interactions
- ๐ Handles layout & orientation changes smartly
- ๐ฏ Compatible with Expo
- ๐ง Flexible config
- ๐ Supports props live update
- ๐ Configurable animation
- ๐จ Follows Material Design principles
- ๐ Runs on the web
- โ Written in TypeScript
npm install @devvie/bottom-sheet
or
yarn add @devvie/bottom-sheet
Opening and closing the bottom sheet is done imperatively, so just pass a ref
to the bottom sheet and call the open
or close
methods via the ref
instance to open and close the bottom sheet respectively.
import React, { useRef } from 'react';
import BottomSheet, { BottomSheetMethods } from '@devvie/bottom-sheet';
import { Button, View } from 'react-native';
const App = () => {
const sheetRef = useRef<BottomSheetMethods>(null);
return (
<View>
<Button title="Open" onPress={() => sheetRef.current?.open()} />
<BottomSheet ref={sheetRef}>
<Text>
The smart ๐, tiny ๐ฆ, and flexible ๐ bottom sheet your app craves ๐
</Text>
</BottomSheet>
</View>
);
};
export default App;
import React, { useRef } from 'react';
import BottomSheet, { BottomSheetMethods } from '@devvie/bottom-sheet';
import { Button, View } from 'react-native';
const App = () => {
const sheetRef = useRef(null);
return (
<View>
<Button title="Open" onPress={() => sheetRef.current?.open()} />
<BottomSheet ref={sheetRef}>
<Text>
The smart ๐, tiny ๐ฆ, and flexible ๐ bottom sheet your app craves ๐
</Text>
</BottomSheet>
</View>
);
};
The bottom sheet component uses and handles pan gestures internally, so to avoid scroll/pan misbehavior with its container, DO NOT put it inside a container that supports panning e.g ScrollView
. You can always put it just next to the ScrollView
and use React Fragment
or a View
to wrap them and everything should be okay.
<ScrollView>
<BottomSheet>...</BottomSheet>
</ScrollView>
<>
<ScrollView>...</ScrollView>
<BottomSheet>...</BottomSheet>
</>
The bottom sheet is highly configurable via props. All props works for both Android
and iOS
except those prefixed with android_
and ios_
, which works for only Android
and iOS
respectively.
Property | Type | Default | Description | Required |
---|---|---|---|---|
android_backdropMaskRippleColor |
string | OpaqueColorValue |
Color of the ripple effect when backdrop mask is pressed (Android Only). | No | |
android_closeOnBackPress |
boolean |
true |
Determines whether the sheet will close when the device back button is pressed (Android Only). | No |
animationType |
'slide' | 'spring' | 'fade' | ANIMATIONS |
'slide' |
Animation to use when opening and closing the bottom sheet. | No |
backdropMaskColor |
string | OpaqueColorValue |
'#00000052' |
Color of the scrim or backdrop mask. | No |
children |
ViewProps['children'] | React.FunctionComponent<{_animatedHeight: Animated.Value}> |
null |
Contents of the bottom sheet. | Yes |
closeDuration |
number |
500 |
Duration for sheet closing animation. | No |
closeOnBackdropPress |
boolean |
true |
Determines whether the bottom sheet will close when the scrim or backdrop mask is pressed. | No |
closeOnDragDown |
boolean |
true |
Determines whether the bottom sheet will close when dragged down. | No |
containerHeight |
ViewStyle['height'] |
DEVICE SCREEN HEIGHT |
Height of the bottom sheet's overall container. | No |
customBackdropComponent |
React.FunctionComponent<{_animatedHeight: Animated.Value}> |
null |
Custom component for sheet's scrim or backdrop mask. | No |
customBackdropPosition |
"top" | "behind" |
'behind' |
Determines the position of the custom scrim or backdrop component. 'behind' puts it behind the keyboard and `'top'`` puts it atop the keyboard. |
No |
customDragHandleComponent |
React.FC<{_animatedHeight: Animated.Value}> |
Custom drag handle component to replace the default bottom sheet's drag handle. | No | |
customEasingFunction |
AnimationEasingFunction |
ANIMATIONS.SLIDE |
Custom easing function for driving sheet's animation. | No |
disableBodyPanning |
boolean |
false |
Prevents the bottom sheet from being dragged/panned down on its body. | No |
disableDragHandlePanning |
boolean |
false |
Prevents the bottom sheet from being panned down by dragging its drag handle. | No |
dragHandleStyle |
ViewStyle |
Extra styles to apply to the drag handle. | No | |
height |
number | string |
'50%' |
Height of the bottom sheet when opened. Relative to containerHeight prop |
No |
hideDragHandle |
boolean |
false |
When true, hides the sheet's drag handle. | No |
modal |
boolean |
true |
Determines whether the sheet is a modal. A modal sheet has a scrim or backdrop mask, while a standard (non-modal) sheet doesn't. | No |
openDuration |
number |
500 |
Duration for sheet opening animation. | No |
style |
Omit<ViewStyle, 'height' | 'minHeight' | 'maxHeight' | 'transform:[{translateY}]'> |
Extra styles to apply to the bottom sheet. | No |
Flexibility is a focus for this bottom sheet, these few examples shows certain behaviors of the bottom sheet and what can be achieved by tweaking its props.
Android | iOS |
---|---|
Android | iOS |
---|---|
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT
see LICENSE
</> with ๐ by Devvie โ