An interactive sheet modal, fully customizable, performance focused
- Supports modal and detached view
- Smooth animations and snapping
- Configurable snap points
- Nested
SheetModalProviders
that automatically inherit props - Runs on Expo & React Native
- Compatible with iOS, Android & web
- Written in TypeScript
$ yarn add @myalbum/sheet-modal
$ expo install @myalbum/sheet-modal
This library depends on React Native Reanimated & React Native Gesture Handler
$ yarn add react-native-reanimated react-native-gesture-handler
$ npx expo install react-native-reanimated react-native-gesture-handler
Important
React Native Gesture Handler needs extra installation steps, please follow their guide
React Native Reanimated needs extra installation steps, please follow their guide
Below a simple usage example
import React, { useCallback, useRef } from 'react';
import { SheetModal, SheetModalMethods, ScrollView } from '@myalbum/sheet-modal';
export default function App() {
const sheetModalRef = useRef<SheetModalMethods>(null);
const openSheetModal = useCallback(() => {
sheetModalRef.current?.snapToIndex(0);
}, []);
return (
<View>
<Button
title="Open sheet modal"
onPress={openSheetModal}
/>
<SheetModal
ref={sheetModalRef}
snapPoints={[200, "100%"]}
>
<ScrollView>
<Text>Sheet modal content</Text>
</ScrollView>
</SheetModal>
</View>
);
}
- Responsive
Auto switch between detached/attached based on screensize - Advanced usage
useSheetModal hook and get access to internal methods/state
The props below can be used in any SheetModalProvider
or SheetModal
. The props will inherit from nested SheetModalProvider
to SheetModal
Prop | Type | Default | Description |
---|---|---|---|
withClosebutton |
boolean |
true |
Render a close button in the header |
withFocusTrap |
boolean |
true |
Trap focus inside Modal (web) |
withBackdrop |
boolean |
true |
Render a backdrop behind the sheet modal |
snapPoints |
Array<number | string> |
["100%"] |
Array of snappoints for the sheet modal, in pixels (number) or percentage (string). If a snapPoint is greater than the content height, the sheet modal will not expand beyond the actual content size. |
snapPointIndex |
number |
-1 |
Initial snap index. Provide -1 to initiate sheet in closed state |
panDownToClose |
boolean |
true |
Allow panning down to close the sheet modal |
panContent |
boolean |
true |
Allow panning the content of the sheet modal, when false and panDownToClose is true, only the handle can be used to pan |
minHeight |
number |
50 |
Minimum height of the sheet modal |
autoShrink |
boolean |
true |
Shrink the sheet modal to the content height when the content is smaller than the modal. |
closeY |
number |
-50 |
Y position of the sheet modal when closed, should be something (0 - shadow size) |
detached |
boolean |
false |
Detach the sheet modal from the bottom of the screen |
position |
["bottom" | "center" | "top", "left" | "center" | "right"] |
["center", "center"] |
Position of the sheet modal, [vertical, horizontal] Attached mode ignores vertical position |
offset |
[number, number] |
[50, 30] |
Offset from the screen, [vertical, horizontal] |
onClosed |
function |
undefined |
Optional callback triggered after closing animation ended |
onOpened |
function |
undefined |
Optional callback triggered after opening animation ended |
onSnapPointChanged |
function |
undefined |
Optional callback triggered when the snap point has been changed |
Prop | Description |
---|---|
containerStyle |
Styling for the modal container |
headerStyle |
Styling for the header |
handleStyle |
Styling for the handle |
closeButtonStyle |
{Both are optional and will inherit from nested SheetModalProvider |
Prop | Type | Description |
---|---|---|
backdropComponent |
() => ReactNode |
Custom backdrop component |
closeButtonComponent |
() => ReactNode |
Custom close button component |
handleComponent |
() => ReactNode |
Custom handle component |
The methods below can be used in the SheetModal
component
Method | Description |
---|---|
snapToIndex: (index: number, animate?: boolean) => void |
Snap to a specific snap point |
close: () => void |
Closes the sheet modal |
autoFocus: (node: ReactNode) => void |
Sets the active focus on a node |
setContentLayout: (w: number, h: number) => void |
Manually set the content layout |
See the examples directory for a full example of how to use the library.
First bootstrap the examples by installing the dependencies
$ yarn bootstrap
Important
For the bare example you need prepare the Pod project before running the example, this can be done by running: $ cd examples/bare && yarn prepare-ios
After that you can run the examples:
$ yarn expo
to start the expo example$ yarn bare
to start the bare react-native example
This package is compatible with React Native, but due to a bug in react-native-reanimated
it can cause some issues when newarch/bridgeless is enabled.
ReanimatedCommitMarker::ReanimatedCommitMarker() {
react_native_assert(reanimatedCommitFlag_ != true);
reanimatedCommitFlag_ = true;
}
This project is licensed under the MIT License - see the LICENSE file for details
See CONTRIBUTING.md for more information on how to contribute to this project.