npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rn-modal-bottom-sheet

v2.4.2

Published

rn-modal-bottom-sheet - A performant, gesture-enabled bottom sheet component for React Native with snap points, scroll-to-expand, and pull-to-collapse. Zero native dependencies, works with Expo.

Readme

rn-modal-bottom-sheet

npm version npm downloads GitHub stars

rn-modal-bottom-sheet is a performant, gesture-enabled bottom sheet component for React Native with snap points, scroll-to-expand, and pull-to-collapse functionality. Zero native dependencies, works seamlessly with Expo!

📱 Demo

🎥 Click here to view Demo Video - See the modal sheet in action with snap points, scroll-to-expand, and smooth animations!

✨ Features

  • 🎯 Snap Points - Multiple snap positions with intelligent detection
  • 📜 Scroll-to-Expand - Automatically expand to next snap point while scrolling
  • 👆 Pull-to-Collapse - Pull down at the top to collapse or close
  • 🎨 Smooth Animations - Buttery smooth bezier easing with 60fps performance
  • 🚀 High Performance - Transform-based animations, no layout recalculations
  • 🎯 Zero Native Dependencies - Built with React Native's Animated API
  • 📱 Cross Platform - Works on both iOS and Android
  • 🎭 Backdrop Animation - Independent opacity animation for backdrop
  • 👆 Gesture Support - Drag to close with customizable threshold
  • 🎨 Fully Customizable - Customize colors, dimensions, and animations
  • 📦 Lightweight - Minimal overhead, no external dependencies
  • ARIA Compliant - Full accessibility support with ARIA attributes
  • 🔒 TypeScript Support - Full TypeScript definitions included

📦 Installation

npm install rn-modal-bottom-sheet react-native-safe-area-context
# or
yarn add rn-modal-bottom-sheet react-native-safe-area-context

Peer Dependencies

This package requires the following peer dependencies:

  • react-native-safe-area-context (>=3.0.0)
  • react-native-gesture-handler (>=2.0.0) - Only needed if using enableDragAndDrop
  • react-native-reanimated (>=2.0.0) - Only needed if using SharedValue for snap points

🚀 Quick Start

Basic Usage

import React, { useRef } from 'react';
import { Button, Text, View } from 'react-native';
import ModalSheet, { ModalSheetRef } from 'rn-modal-bottom-sheet';

function App() {
  const sheetRef = useRef<ModalSheetRef>(null);

  return (
    <View style={{ flex: 1 }}>
      <Button title="Open Sheet" onPress={() => sheetRef.current?.open()} />

      <ModalSheet ref={sheetRef} height={400}>
        <Text style={{ fontSize: 24, fontWeight: 'bold', textAlign: 'center' }}>
          Hello Bottom Sheet! 👋
        </Text>
      </ModalSheet>
    </View>
  );
}

With Snap Points

import { useRef, useState } from 'react';

function MyComponent() {
  const sheetRef = useRef<ModalSheetRef>(null);
  const [currentIndex, setCurrentIndex] = useState(0);

  return (
    <ModalSheet
      ref={sheetRef}
      snapPoints={[0.3, 0.6, 0.9]} // 30%, 60%, 90% of screen height
      initialSnapIndex={0}
      onSnapPointChange={(index) => setCurrentIndex(index)}
    >
      <Text>Current snap point: {currentIndex}</Text>
    </ModalSheet>
  );
}

With Scroll-to-Expand (NEW in v2.0.0!)

import { ScrollView } from 'react-native';

<ModalSheet
  ref={sheetRef}
  snapPoints={[0.3, 0.9]}
  enableScrollToExpand={true}
  scrollExpandThreshold={20}
>
  <ScrollView
    onScroll={(e) => sheetRef.current?.handleScroll(e)}
    onScrollBeginDrag={(e) => sheetRef.current?.handleScrollBeginDrag(e)}
    onScrollEndDrag={(e) => sheetRef.current?.handleScrollEndDrag(e)}
    scrollEventThrottle={16}
  >
    {/* Your scrollable content */}
  </ScrollView>
</ModalSheet>

With Drag & Drop Support (NEW in v2.1.0!)

import DraggableFlatList from 'react-native-draggable-flatlist';

<ModalSheet
  ref={sheetRef}
  height={500}
  enableDragAndDrop={true} // Automatically wraps in GestureHandlerRootView
>
  <DraggableFlatList
    data={items}
    renderItem={renderItem}
    keyExtractor={(item) => item.key}
    onDragEnd={({ data }) => setItems(data)}
  />
</ModalSheet>

📚 API Reference

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | ReactNode | Required | Content to be rendered inside the bottom sheet | | height | number | 400 | Height of the bottom sheet in pixels | | snapPoints | number[] | - | Array of snap points as percentages (0-1) or pixels | | initialSnapIndex | number | 0 | Which snap point to open to initially | | enableScrollToExpand | boolean | true | Enable scroll-to-expand behavior | | scrollExpandThreshold | number | 50 | Pixels to scroll before triggering transition | | enableDragAndDrop | boolean | false | Enable automatic GestureHandlerRootView wrapping for gesture components | | avoidKeyboard | boolean | false | Enable keyboard avoidance to push sheet up when keyboard appears | | keyboardOffset | number | 0 | Additional offset when keyboard is shown (in pixels) | | onSnapPointChange | (index: number) => void | - | Callback when snap point changes | | onClose | () => void | - | Callback when the sheet is closed | | onOpen | () => void | - | Callback when the sheet is opened | | backgroundColor | string | 'white' | Background color of the sheet | | borderRadius | number | 20 | Border radius of the top corners | | showHandle | boolean | true | Show the drag handle indicator | | handleColor | string | '#DDD' | Color of the drag handle | | backdropOpacity | number | 0.5 | Opacity of the backdrop (0-1) | | dragThreshold | number | 125 | Distance to drag before sheet closes | | applyBottomInset | boolean | true | Apply bottom safe area inset padding to content | | aria-label | string | 'Bottom sheet' | Accessible label for the modal | | aria-describedby | string | - | ID of element describing the modal | | backdropAriaLabel | string | 'Close bottom sheet' | Accessible label for backdrop |

Methods (via ref)

| Method | Description | |--------|-------------| | open() | Opens the bottom sheet | | close() | Closes the bottom sheet | | present() | Alias for open() | | dismiss() | Alias for close() | | snapToPoint(index) | Snap to a specific snap point by index | | handleScroll(event) | Process scroll events for scroll-to-expand | | handleScrollBeginDrag(event) | Track scroll start position | | handleScrollEndDrag(event) | Handle pull-to-collapse gestures |

🎨 Examples

Custom Styling

<ModalSheet
  ref={sheetRef}
  height={500}
  backgroundColor="#1a1a1a"
  borderRadius={30}
  handleColor="#666"
  backdropOpacity={0.8}
>
  <Text style={{ color: 'white' }}>Dark Theme Sheet</Text>
</ModalSheet>

Music Player (Two Snap Points)

<ModalSheet
  ref={sheetRef}
  snapPoints={[0.15, 0.9]} // Mini player and full player
  initialSnapIndex={0}
  enableScrollToExpand={true}
>
  {/* Your music player UI */}
</ModalSheet>

Scrollable Content

<ModalSheet ref={sheetRef} height={600}>
  <ScrollView showsVerticalScrollIndicator={false}>
    {items.map((item) => (
      <Text key={item.id}>{item.name}</Text>
    ))}
  </ScrollView>
</ModalSheet>

With Safe Area Insets

// The bottom safe area inset is applied by default
<ModalSheet ref={sheetRef} height={400}>
  <View>
    <Text>Content with safe area padding</Text>
    {/* Bottom padding automatically applied for devices with home indicator */}
  </View>
</ModalSheet>

// Disable bottom inset if not needed
<ModalSheet ref={sheetRef} height={400} applyBottomInset={false}>
  <View>
    <Text>Content without safe area padding</Text>
  </View>
</ModalSheet>

🎯 Scroll-to-Expand Behavior

The scroll-to-expand feature allows users to naturally expand the sheet by scrolling down:

  • Gentle scroll down: Expands to next snap point
  • Medium swipe down: Jumps 2 snap points
  • Fast swipe down: Jumps to maximum height

And collapse by pulling up at the top:

  • Gentle pull up: Collapses to previous snap point
  • Fast swipe up: Closes the sheet immediately

♿ Accessibility

Fully accessible with WCAG compliance:

  • ARIA Attributes - Modern aria-label, aria-modal, aria-describedby
  • Screen Reader Support - Proper labeling for all interactive elements
  • Keyboard Navigation - Full keyboard support
  • Focus Management - Correct focus handling
  • Gesture Alternatives - Alternative methods for all gestures

🚀 Performance

  • Transform-Based: Uses translateY transforms for 60fps animations
  • Native Driver: All animations run on the UI thread
  • Smooth Easing: Custom bezier curve (0.25, 0.1, 0.25, 1)
  • No Layout Recalculations: Content pre-rendered once
  • Optimized: Efficient re-renders and memory management

📱 Platform Support

  • ✅ iOS
  • ✅ Android
  • ✅ Expo
  • ✅ React Native CLI

🔗 Links

📄 License

MIT © Christian

☕ Support

If you find this project helpful, consider supporting:

Buy Me A Coffee


Made with ❤️ using React Native