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-bounds

v0.5.0

Published

React Native helpers for screen bounds, safe area, keyboard-safe layouts, notch, gesture navigation, status bar, and Android system bar insets.

Readme

react-native-bounds

npm version license React Native

Reliable screen bounds, safe-area helpers, keyboard-safe layout primitives, Android navigation-bar detection, status-bar height, and notch/cutout handling for React Native.

react-native-bounds gives you a small API for layouts that need to avoid the real edges of the device: status bars, waterdrop cameras, notches, home indicators, Android three-button navigation, and Android gesture areas.

Highlights

  • Detects Android status bar height.
  • Handles Android waterdrop camera and display cutout top insets.
  • Detects Android three-button navigation bar space.
  • Detects Android gesture navigation space when visible.
  • Reads native Android WindowInsets for production accuracy.
  • Falls back to JavaScript estimates if the native module is unavailable.
  • Estimates iOS notch, Dynamic Island, and home indicator safe areas.
  • Returns usable layout frame after insets.
  • Recomputes on rotation and window-size changes.
  • Detects keyboard visibility, height, animation duration, and frame changes.
  • Provides opt-in keyboard-safe containers for forms, bottom CTAs, and chat composers.
  • No extra runtime dependency.

Installation

npm install react-native-bounds

or:

yarn add react-native-bounds

Expo

This package includes Android native code. It works in Expo dev builds and prebuild/native projects.

It will not load the Android native module inside Expo Go.

npx expo run:android

Quick Start

import React from "react";
import { Text, View } from "react-native";
import { useScreenSafeArea } from "react-native-bounds";

export default function App() {
  const bounds = useScreenSafeArea();

  return (
    <View
      style={{
        flex: 1,
        paddingTop: bounds.insets.top,
        paddingBottom: bounds.insets.bottom,
        paddingLeft: bounds.insets.left,
        paddingRight: bounds.insets.right,
      }}
    >
      <Text>Status bar: {bounds.statusBarHeight}</Text>
      <Text>Bottom inset: {bounds.insets.bottom}</Text>
      <Text>Android nav mode: {bounds.androidNavigationMode}</Text>
      <Text>Usable frame height: {bounds.frame.height}</Text>
    </View>
  );
}

Safe Area View

Use ScreenSafeAreaView when you want safe-area padding without writing layout math yourself.

import React from "react";
import { Text } from "react-native";
import { ScreenSafeAreaView } from "react-native-bounds";

export default function Screen() {
  return (
    <ScreenSafeAreaView edges={["top", "bottom"]} style={{ flex: 1 }}>
      <Text>This content avoids the status bar and bottom system area.</Text>
    </ScreenSafeAreaView>
  );
}

Set keyboardAware when the same container should lift its bottom padding with the keyboard. The default is false, so existing layouts keep the same behavior.

import React from "react";
import { TextInput } from "react-native";
import { ScreenSafeAreaView } from "react-native-bounds";

export default function FormScreen() {
  return (
    <ScreenSafeAreaView edges={["top", "bottom"]} keyboardAware style={{ flex: 1 }}>
      <TextInput placeholder="Email" />
    </ScreenSafeAreaView>
  );
}

Keyboard Awareness

Use useKeyboard when you only need keyboard state.

import { useKeyboard } from "react-native-bounds";

const keyboard = useKeyboard();

console.log(keyboard.isKeyboardVisible);
console.log(keyboard.keyboardHeight);
console.log(keyboard.keyboardAnimationDuration);

KeyboardProvider is optional. Use it near the root when many descendants read keyboard state.

import { KeyboardProvider } from "react-native-bounds";

export default function App() {
  return <KeyboardProvider>{/* app */}</KeyboardProvider>;
}

For forms and long content, use KeyboardAwareScrollView.

import { KeyboardAwareScrollView } from "react-native-bounds";

export function SettingsForm() {
  return (
    <KeyboardAwareScrollView>
      {/* inputs and actions */}
    </KeyboardAwareScrollView>
  );
}

For bottom CTAs, search bars, and chat composers, use KeyboardStickyView.

import { Pressable, Text } from "react-native";
import { KeyboardStickyView } from "react-native-bounds";

export function BottomAction() {
  return (
    <KeyboardStickyView style={{ paddingHorizontal: 16 }}>
      <Pressable>
        <Text>Continue</Text>
      </Pressable>
    </KeyboardStickyView>
  );
}

On Android, keyboard-aware components assume your activity uses adjustResize, so they avoid adding keyboard height on top of an already resized app window. For non-resizing overlays, portals, modals, or bottom sheets, pass keyboardOffsetStrategy="max" or keyboardOffsetStrategy="keyboard".

Use useKeyboardSafeArea when you want the combined safe-area and keyboard math directly.

import { useKeyboardSafeArea } from "react-native-bounds";

const layout = useKeyboardSafeArea({
  extraOffset: 12,
  offsetStrategy: "max",
});

console.log(layout.insets.bottom);
console.log(layout.keyboardBottomInset);
console.log(layout.bottomInset);

Use Without A Component

import { getScreenSafeArea } from "react-native-bounds";

const bounds = getScreenSafeArea();

console.log(bounds.insets);
console.log(bounds.frame);
console.log(bounds.androidNavigationMode);
console.log(bounds.navigationBarHeight);

What You Get

| Field | Description | | --- | --- | | insets | Top, right, bottom, and left safe-area/system-bar inset values. | | frame | Usable content frame after subtracting insets. | | statusBarHeight | Android status bar or iOS top safe-area estimate. | | navigationBarHeight | Android bottom/side navigation-bar size. | | androidNavigationMode | "none", "gesture", "three-button", or "unknown". | | androidNavigationBarPosition | "none", "bottom", "right", "left", or "unknown". | | hasGestureNavigation | True for iOS home indicator or likely Android gesture navigation. | | hasNavigationBar | True when Android navigation-bar space is visible. | | isEstimated | False when Android native insets are used; true for JS estimates. |

Keyboard Fields

| Field | Description | | --- | --- | | isKeyboardVisible | True when React Native reports a visible software keyboard frame. | | keyboardHeight | Keyboard overlap height in pixels. Hardware keyboards report 0. | | keyboardAnimationDuration | Native keyboard animation duration when available. | | keyboardBottomInset | Bottom inset from the selected keyboard offset strategy. | | bottomInset | keyboardBottomInset plus extraOffset, ready for padding or sticky positioning. |

Android Navigation Detection

Android can be tricky:

  • Some devices show a classic three-button navigation bar.
  • Some devices use a small gesture area.
  • Some devices report screen and window as the same size even when system bars are visible.
  • Phones with waterdrop cameras may need display cutout safe insets, not just status-bar height.

react-native-bounds handles this by reading native Android WindowInsets when the native module is linked. That lets it detect real status-bar, display-cutout, and navigation-bar insets.

const bounds = getScreenSafeArea();

if (bounds.androidNavigationMode === "three-button") {
  // Keep fixed actions above the Android navigation bar.
}

if (bounds.androidNavigationMode === "gesture") {
  // Avoid placing important controls too close to the gesture area.
}

if (bounds.insets.top > 0) {
  // Content is below the status bar or waterdrop camera cutout.
}

Returned Type

type ScreenSafeArea = {
  insets: {
    top: number;
    right: number;
    bottom: number;
    left: number;
  };
  frame: {
    x: number;
    y: number;
    width: number;
    height: number;
  };
  systemBars: {
    top: number;
    right: number;
    bottom: number;
    left: number;
  };
  orientation: "portrait" | "landscape" | "square";
  statusBarHeight: number;
  navigationBarHeight: number;
  androidNavigationMode: "none" | "gesture" | "three-button" | "unknown";
  androidNavigationBarPosition: "none" | "bottom" | "right" | "left" | "unknown";
  hasNotch: boolean;
  hasHomeIndicator: boolean;
  hasNavigationBar: boolean;
  hasGestureNavigation: boolean;
  isEstimated: boolean;
  isIOS: boolean;
  isAndroid: boolean;
  isPortrait: boolean;
  isLandscape: boolean;
  screenWidth: number;
  screenHeight: number;
  windowWidth: number;
  windowHeight: number;
  screenScale: number;
  fontScale: number;
};

Common Patterns

Floating Bottom Button

const bounds = useScreenSafeArea();

return (
  <Pressable
    style={{
      position: "absolute",
      left: 16,
      right: 16,
      bottom: Math.max(16, bounds.insets.bottom + 12),
    }}
  >
    <Text>Continue</Text>
  </Pressable>
);

Full Screen Content

const bounds = useScreenSafeArea();

return (
  <View
    style={{
      width: bounds.frame.width,
      height: bounds.frame.height,
      marginTop: bounds.insets.top,
      marginLeft: bounds.insets.left,
    }}
  />
);

Debug Device Insets

const bounds = useScreenSafeArea();

console.log({
  insets: bounds.insets,
  statusBarHeight: bounds.statusBarHeight,
  navigationBarHeight: bounds.navigationBarHeight,
  androidNavigationMode: bounds.androidNavigationMode,
  androidNavigationBarPosition: bounds.androidNavigationBarPosition,
  isEstimated: bounds.isEstimated,
});

Accuracy Notes

Android:

  • Uses native WindowInsets when installed in a real Android build.
  • Includes status bar, navigation bar, and display cutout safe top inset.
  • Falls back to StatusBar.currentHeight and dimension-gap estimates if native insets are unavailable.

iOS:

  • Uses JavaScript estimates.
  • Detects common modern iPhone notch and Dynamic Island profiles.
  • Estimates home indicator and landscape side insets.

For exact native safe-area behavior across every platform, OS version, and edge-to-edge mode, react-native-safe-area-context is still a strong choice. Use react-native-bounds when you want a tiny focused helper with Android navigation detection built in.

API

useScreenSafeArea(): ScreenSafeArea
getScreenSafeArea(): ScreenSafeArea
useKeyboard(): KeyboardState
useKeyboardSafeArea(options?: KeyboardSafeAreaOptions): KeyboardSafeArea
getKeyboardBottomInset(safeAreaBottomInset, keyboardHeight, offsetStrategy): number
<ScreenSafeAreaView edges={["top", "bottom"]} style={{ flex: 1 }}>
  {children}
</ScreenSafeAreaView>

<KeyboardSafeAreaView edges={["top", "bottom"]} style={{ flex: 1 }}>
  {children}
</KeyboardSafeAreaView>

<KeyboardAwareScrollView>
  {children}
</KeyboardAwareScrollView>

<KeyboardStickyView>
  {children}
</KeyboardStickyView>

License

MIT