SheetModal
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
Index
Installation
Install with yarn
$ yarn add @myalbum/sheet-modal
Install with Expo
$ expo install @myalbum/sheet-modal
Dependencies
This library depends on React Native Reanimated & React Native Gesture Handler
Install with yarn
$ yarn add react-native-reanimated react-native-gesture-handler
Install with expo
$ 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
Usage
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
Props
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 |
Props for custom styling
Prop | Description |
---|
containerStyle | Styling for the modal container |
headerStyle | Styling for the header |
handleStyle | Styling for the handle |
closeButtonStyle | { iconColor: string backgroundColor: string } Both are optional and will inherit from nested SheetModalProvider |
Props for custom components
Prop | Type | Description |
---|
backdropComponent | () => ReactNode | Custom backdrop component |
closeButtonComponent | (sheetModal: SheetModalMethods) => ReactNode | Custom close button component |
handleComponent | () => ReactNode | Custom handle component |
Methods
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: (onClosed: () => void) => 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 |
Examples
See the examples directory for a full example of how to use the library.
Running the examples
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
Known issues
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;
}
License
This project is licensed under the MIT License - see the LICENSE file for details
Contributing
See CONTRIBUTING.md for more information on how to contribute to this project.
Build with ❤️