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

react-native-keyboard-sheet

v0.1.0

Published

A keyboard-aware React Native bottom sheet with fixed header, scrollable content, fixed footer, and safe-area support.

Readme

react-native-keyboard-sheet

A keyboard-aware React Native bottom sheet that keeps headers and submit buttons fixed above the keyboard on Android and iOS. Only the middle content scrolls.

Screenshots

| Example app | Compact content | RTL long form with keyboard | | --- | --- | --- | | | | |

Why

Keyboard bugs usually appear when several systems compete to move the same view: KeyboardAvoidingView, modal keyboard avoidance, Android window resizing, automatic scrolling, or an iOS keyboard manager. This package owns that layout contract in one place.

Features

  • Android and iOS keyboard frame handling
  • Fixed header and footer
  • Scrollable middle content
  • Content-sized sheets with a safe maximum height
  • Safe-area support
  • Rotation and screen-size changes
  • Optional IQKeyboardManager-style adapter
  • RTL/LTR agnostic layout
  • TypeScript-first API
  • No native code and no required modal dependency

Installation

npm install react-native-keyboard-sheet react-native-safe-area-context

Wrap the application with SafeAreaProvider if it is not already wrapped:

import { SafeAreaProvider } from "react-native-safe-area-context";

export default function App() {
  return <SafeAreaProvider>{/* application */}</SafeAreaProvider>;
}

Basic usage

import { useState } from "react";
import { Button, Text, TextInput } from "react-native";
import { KeyboardSheet } from "react-native-keyboard-sheet";

export function ReportSheet() {
  const [visible, setVisible] = useState(false);
  const [reason, setReason] = useState("");

  return (
    <>
      <Button title="Report" onPress={() => setVisible(true)} />
      <KeyboardSheet
        visible={visible}
        onClose={() => setVisible(false)}
        header={<Text>Report content</Text>}
        footer={<Button title="Submit" onPress={() => undefined} />}
      >
        <TextInput
          multiline
          onChangeText={setReason}
          value={reason}
          underlineColorAndroid="transparent"
        />
      </KeyboardSheet>
    </>
  );
}

The sheet measures its natural content height. When the keyboard leaves enough room, the sheet stays compact. On smaller devices, the header and footer remain fixed and only the body becomes scrollable.

iOS keyboard managers

If the app uses a global manager such as react-native-keyboard-manager, pass an adapter so the package can temporarily disable it while the sheet is visible:

import KeyboardManager from "react-native-keyboard-manager";

const keyboardManagerAdapter = {
  getEnabled: () => KeyboardManager.isEnabled(),
  setEnabled: (enabled: boolean) => KeyboardManager.setEnable(enabled),
};

<KeyboardSheet
  keyboardManagerAdapter={keyboardManagerAdapter}
  visible={visible}
  onClose={close}
>
  {/* content */}
</KeyboardSheet>;

Memoize the adapter or define it outside the component so it retains stable identity. getEnabled is optional, but providing it lets the sheet restore a manager that was already disabled instead of assuming its prior state was enabled.

API

| Prop | Type | Default | Description | | --- | --- | --- | --- | | visible | boolean | required | Controls presentation. | | onClose | () => void | required | Called for backdrop and system back actions. | | children | ReactNode | required | Scrollable sheet content. | | header | ReactNode | — | Fixed content above the scroll area. | | footer | ReactNode | — | Fixed content above the keyboard. | | maxHeightRatio | number | 0.88 | Maximum fraction of screen height. | | keyboardGap | number | 8 | Gap above an open keyboard. | | topGap | number | 12 | Minimum distance from the top safe area. | | scrollEnabled | boolean | true | Enables body scrolling. | | closeOnBackdropPress | boolean | true | Enables backdrop dismissal. | | dismissKeyboardOnClose | boolean | true | Dismisses the keyboard before closing. | | keyboardManagerAdapter | KeyboardManagerAdapter | — | Temporarily disables an external iOS keyboard manager. | | layoutDirection | "ltr" \| "rtl" | System direction | Explicit sheet and scroll layout direction. | | showHandle | boolean | true | Displays the drag-style visual handle. | | backdropAccessibilityLabel | string | Dismiss | Accessible label for the dismissible backdrop. | | onShow / onDismiss | native modal callbacks | — | Presentation lifecycle callbacks; onShow is useful for reliably focusing an input. |

The component also exposes style props for the sheet, backdrop, handle, header, footer, and scroll content.

Layout rules

Do not wrap KeyboardSheet in KeyboardAvoidingView, and do not enable another modal keyboard-avoidance mechanism around it. The component must be the only owner of keyboard movement.

On Android, use the normal adjustResize behavior (Expo: android.softwareKeyboardLayoutMode: "resize"). The component reconciles the resized modal viewport with the keyboard frame so any resize already applied is not applied a second time. On iOS, it follows docked keyboard frame changes. Floating and undocked keyboards do not move the entire bottom-anchored sheet.

Keep the sheet mounted near the app/root screen rather than inside a parent with clipping styles. React Native's native Modal provides the presentation boundary.

Example app

The Expo app in example includes compact, long, fixed-footer, multiline, RTL, and external keyboard-manager scenarios:

cd example
npm install
npm run ios
# or: npm run android

Development

npm install
npm run typecheck
npm test
npm run build
npm run pack:check

License

MIT