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 🙏

© 2025 – Pkg Stats / Ryan Hefner

szn-ui-react-native-bottom-sheet

v1.0.14

Published

A customizable React Native bottom sheet component with gesture support, keyboard awareness, and smooth animations.

Downloads

41

Readme

React Native Bottom Sheet

A smooth, customizable bottom sheet component for React Native with gesture support and TypeScript definitions specifically built for expo SDK 54 and react native reanimated v4 . Ensure that you're using the latest version as previous versions may be broken or depreciated.

Bottom Sheet Demo

Features

  • 🎯 TypeScript Support - Full TypeScript definitions included
  • 🎨 Customizable - Highly customizable appearance and behavior
  • 📱 Cross Platform - Works on both iOS and Android
  • Gesture Support - Smooth drag-to-dismiss functionality
  • ⌨️ Keyboard Aware - Proper keyboard handling
  • 🎭 Flexible Content - Support for any content with scroll view
  • 🎪 Animation - Smooth enter/exit animations

Installation

npm install szn-ui-react-native-bottom-sheet

Peer Dependencies

This package requires the following peer dependencies:

npm install react-native-gesture-handler react-native-reanimated

Make sure to follow the installation instructions for:

Usage

import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheet } from "szn-ui-react-native-bottom-sheet";

const App = (): JSX.Element => {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button title="Open Bottom Sheet" onPress={() => setIsVisible(true)} />
      
      <BottomSheet
        isVisible={isVisible}
        onClose={() => setIsVisible(false)}
      >
        <View style={{ padding: 20 }}>
          <Text>Hello from bottom sheet!</Text>
        </View>
      </BottomSheet>
    </View>
  );
};

export default App;

Props

| Prop | Type | Default | Description | | ----------------- | ------------ | --------------------- | ------------------------------------------------------------------------ | | isVisible | boolean | Required | Controls the visibility of the bottom sheet | | onClose | () => void | Required | Callback when the sheet should be closed | | children | ReactNode | Required | Content to render inside the bottom sheet | | height | number | SCREEN_HEIGHT * 0.9 | Height of the bottom sheet | | backgroundColor | string | 'white' | Background color of the bottom sheet | | showDragHandle | boolean | true | Whether to show the drag handle | | containerStyle | ViewStyle | undefined | Additional styles for the sheet container | | title | string | undefined | Title text to display in the header | | showHeader | boolean | false | Whether to show the header with title and cancel button | | cancelText | string | 'Cancel' | Text for the cancel button in header |

You can customize the sheet's background using either the backgroundColor prop or via containerStyle, but if both are provided, the backgroundColor prop takes precedence.

Examples

With Header

<BottomSheet
  isVisible={isVisible}
  onClose={() => setIsVisible(false)}
  showHeader
  title="Settings"
  cancelText="Done"
>
  <View style={{ padding: 20 }}>
    <Text>Settings content here</Text>
  </View>
</BottomSheet>

If you wish to use your own custom close button instead of the cancel text prop

import React, { useRef, useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { BottomSheet, BottomSheetRef } from 'szn-ui-react-native-bottom-sheet';
import { Ionicons } from '@expo/vector-icons';

export default function MyScreen(): JSX.Element {
  const [isVisible, setIsVisible] = useState(false);
  const sheetRef = useRef<BottomSheetRef>(null);

  const handleOpen = () => setIsVisible(true);
  const handleClose = () => setIsVisible(false);

  return (
    <>
      <TouchableOpacity onPress={handleOpen}>
        <Text>Open Bottom Sheet</Text>
      </TouchableOpacity>

      <BottomSheet
        ref={sheetRef}
        isVisible={isVisible}
        onClose={handleClose}
        showHeader={false}
        showDragHandle={true}
        height={600}
      >
        <View className="px-5 pb-3 border-b border-gray-100 flex-row justify-between items-center">
          <Text className="text-lg font-semibold text-gray-900">My Custom Header</Text>
          <TouchableOpacity
            onPress={() => sheetRef.current?.dismiss()}
            className="p-2 bg-gray-100 rounded-full"
          >
            <Ionicons name="close" size={18} color="#374151" />
          </TouchableOpacity>
        </View>

        <Text className="p-5">Sheet Content Here...</Text>
      </BottomSheet>
    </>
  );
}

Custom Height

<BottomSheet
  isVisible={isVisible}
  onClose={() => setIsVisible(false)}
  height={400}
>
  <View style={{ padding: 20 }}>
    <Text>Custom height content</Text>
  </View>
</BottomSheet>

Multi-Step Flow

const [step, setStep] = useState(1);

return (
  <BottomSheet
    isVisible={true}
    onClose={() => {}}
    height={step === 1 ? 200 : step === 2 ? 400 : 600}
  >
    {step === 1 && <StepOne onNext={() => setStep(2)} />}
    {step === 2 && <StepTwo onNext={() => setStep(3)} />}
    {step === 3 && <StepThree />}
  </BottomSheet>
);

Custom Background Color

<BottomSheet
  isVisible={isVisible}
  onClose={() => setIsVisible(false)}
  backgroundColor="#fef2f2"
>
  <View style={{ padding: 20 }}>
    <Text>Light pink background</Text>
  </View>
</BottomSheet>

Custom Styling

<BottomSheet
  isVisible={isVisible}
  onClose={() => setIsVisible(false)}
  containerStyle={{
    backgroundColor: '#f0f0f0',
    borderTopLeftRadius: 30,
    borderTopRightRadius: 30,
  }}
>
  <View style={{ padding: 20 }}>
    <Text>Custom styled content</Text>
  </View>
</BottomSheet>

Full Usage Example

import { useState } from "react";
import {
  KeyboardAvoidingView,
  Platform,
  Pressable,
  ScrollView,
  StyleSheet,
  TextInput,
} from "react-native";
import { BottomSheet } from "szn-ui-react-native-bottom-sheet";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import ParallaxScrollView from "@/components/parallax-scroll-view";
import { Image } from "expo-image";
import { HelloWave } from "@/components/hello-wave";

export default function HomeScreen() {
  const [isBottomSheetVisible, setIsBottomSheetVisible] = useState(false);
  const [inputValue, setInputValue] = useState("");

  const openBottomSheet = () => setIsBottomSheetVisible(true);
  const closeBottomSheet = () => setIsBottomSheetVisible(false);

  return (
    <>
      <ParallaxScrollView
        headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
        headerImage={
          <Image
            source={require("@/assets/images/partial-react-logo.png")}
            style={styles.reactLogo}
          />
        }
      >
        <ThemedView style={styles.titleContainer}>
          <ThemedText type="title">Welcome!</ThemedText>
          <HelloWave />
        </ThemedView>

        <ThemedView style={styles.stepContainer}>
          <Pressable style={styles.bottomSheetButton} onPress={openBottomSheet}>
            <ThemedText style={styles.buttonText}>Open Bottom Sheet</ThemedText>
          </Pressable>
        </ThemedView>
      </ParallaxScrollView>

      <BottomSheet isVisible={isBottomSheetVisible} onClose={closeBottomSheet}>
        <KeyboardAvoidingView
          behavior={Platform.OS === "ios" ? "padding" : undefined}
          style={{ flex: 1 }}
        >
          <ScrollView contentContainerStyle={styles.bottomSheetContent}>
            <ThemedText type="subtitle">Bottom Sheet Test</ThemedText>
            <ThemedText>Your bottom sheet package is working!</ThemedText>

            <TextInput
              placeholder="Type something here..."
              value={inputValue}
              onChangeText={setInputValue}
              style={styles.textInput}
              placeholderTextColor="#999"
            />

            <Pressable style={styles.closeButton} onPress={closeBottomSheet}>
              <ThemedText style={styles.buttonText}>Close</ThemedText>
            </Pressable>
          </ScrollView>
        </KeyboardAvoidingView>
      </BottomSheet>
    </>
  );
}

const styles = StyleSheet.create({
  titleContainer: {
    flexDirection: "row",
    alignItems: "center",
    gap: 8,
  },
  stepContainer: {
    gap: 8,
    marginBottom: 8,
  },
  reactLogo: {
    height: 178,
    width: 290,
    bottom: 0,
    left: 0,
    position: "absolute",
  },
  bottomSheetButton: {
    backgroundColor: "#007AFF",
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8,
    alignItems: "center",
    marginVertical: 20,
  },
  buttonText: {
    color: "#FFFFFF",
    fontWeight: "600",
  },
  bottomSheetContent: {
    padding: 20,
    alignItems: "center",
    gap: 16,
  },
  textInput: {
    width: "100%",
    paddingHorizontal: 16,
    paddingVertical: 12,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: "#ccc",
    color: "#000",
  },
  closeButton: {
    backgroundColor: "#FF3B30",
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 6,
    alignItems: "center",
  },
});

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.