Skip to content

Repository files navigation

React Native Grab

Touch-to-grab context tool for React Native UI changes

mit licence npm downloads Chat PRs Welcome

Bridge the context gap: point at the exact native UI element, capture precise source context, and hand it to your coding agent without guesswork.

Inspired by React Grab — this project brings the same touch-to-grab workflow to React Native.

Requirements

This library supports only the New Architecture with the Fabric renderer. It relies on Fabric’s native view hierarchy and APIs and will not work with the legacy architecture or Paper renderer. Ensure your app has the New Architecture (and Fabric) enabled before using React Native Grab.

Features

  • Point, Don't Describe: Select the exact element on screen instead of describing layouts in prompts.
  • Native Runtime Context: Capture context directly from real React Native views with platform-aware source signals.
  • Faster Agent Edits: Remove the search phase for low-entropy UI changes like spacing, alignment, and copy updates.
  • Metro Middleware Integration: Wire once in Metro and send captured context to your host clipboard.

Installation

npm install react-native-grab

Quick Start

  1. Add React Native Grab middleware to Metro.
  2. Wrap your app root with ReactNativeGrabRoot.
  3. If your app uses native navigators (e.g. native stack, native tabs), wrap each screen with ReactNativeGrabScreen.
  4. Wrap content hosted in a separately presented native sheet or modal with ReactNativeGrabSurface and set active only while it is presented.
  5. Open Dev Menu and choose React Native Grab to start selecting elements.

Quick Configuration Example

// metro.config.js
const { getDefaultConfig } = require("@react-native/metro-config");
const { withReactNativeGrab } = require("react-native-grab/metro");

const config = getDefaultConfig(__dirname);
module.exports = withReactNativeGrab(config);

// app root
import {
  ReactNativeGrabRoot,
  ReactNativeGrabScreen,
  ReactNativeGrabContextProvider,
} from "react-native-grab";

// When using native navigators (native stack, native tabs), wrap each screen:
function HomeScreen() {
  return (
    <ReactNativeGrabScreen>
      <ReactNativeGrabContextProvider value={{ screen: "home" }}>
        {/* screen content */}
      </ReactNativeGrabContextProvider>
    </ReactNativeGrabScreen>
  );
}

export default function AppLayout() {
  return <ReactNativeGrabRoot>{/* app/navigation tree */}</ReactNativeGrabRoot>;
}

API

  • ReactNativeGrabRoot: Root-level provider for grab functionality.
  • ReactNativeGrabScreen: When using native navigators (native stack, native tabs), wrap each screen with this component for accurate selection.
  • ReactNativeGrabSurface: Wraps content hosted in a separately presented native surface. An active surface takes selection priority over the focused screen; when it becomes inactive, selection falls back to the focused screen or root. Unlike ReactNativeGrabRoot and ReactNativeGrabScreen, it does not stretch to fill its parent, so that sheets using content-measured detents can still measure their content. This component is a no-op in production builds.
  • ReactNativeGrabContextProvider: Adds custom metadata to grabbed elements. Nested providers are shallow-merged and child keys override parent keys. This provider is a no-op in production builds.
  • enableGrabbing(): Programmatically enables grabbing flow.
  • setFocusEffect(impl): Overrides the hook used by ReactNativeGrabScreen to detect when a screen is focused. By default the library auto-detects useFocusEffect from expo-router or @react-navigation/native. Call setFocusEffect once at app startup when neither package is present (e.g. a custom router) or when you want explicit control over which implementation is used.
import { setFocusEffect } from "react-native-grab";
import { useFocusEffect } from "my-custom-router";

setFocusEffect(useFocusEffect);

For a native sheet or modal, place ReactNativeGrabSurface inside the presented content and keep active synchronized with its presentation lifecycle:

import { Modal, StyleSheet } from "react-native";
import { ReactNativeGrabSurface } from "react-native-grab";

function DetailsModal({ visible }: { visible: boolean }) {
  return (
    <Modal visible={visible}>
      <ReactNativeGrabSurface active={visible} style={styles.surface}>
        {/* modal or sheet content */}
      </ReactNativeGrabSurface>
    </Modal>
  );
}

const styles = StyleSheet.create({
  surface: {
    flex: 1,
  },
});

ReactNativeGrabSurface renders a View around your content and sizes to that content by default, which is what sheets with content-measured detents need. Pass flex: 1 through style when the surface should fill the presented container instead, as above.

Keep active synchronized with the full presentation lifecycle, including drag-to-dismiss — drive it from the presentation callbacks (onDidDismiss and friends) rather than from the handler that opened the surface. A surface left active after dismissal keeps selection priority and blocks grabbing on the screen behind it.

When grab context is available for a selected element, copied output includes an additional Context: JSON block appended after the existing element preview and stack trace lines.

Documentation

Documentation lives in this repository: callstackincubator/react-native-grab. You can also use the following links to jump to specific topics:

Troubleshooting

Missing React Native Grab in Dev Menu

If you use Expo and provide your own Dev Menu entries, you are most likely overwriting the changes added by React Native Grab.

In that case, import enableGrabbing and call it yourself whenever you want to start grabbing.

import { enableGrabbing } from "react-native-grab";

Made with ❤️ at Callstack

react-native-grab is open source and free to use. If it helps your workflow, please star it 🌟. Callstack is a team of React and React Native engineers, contact us at hello@callstack.com if you need help or just want to say hi.

Like the project? ⚛️ Join the team who does amazing stuff for clients and drives React Native Open Source! 🔥

About

Touch-to-grab context tool for React Native UI changes

Topics

Resources

Stars

227 stars

Watchers

3 watching

Forks

Releases

Used by

Contributors

Languages