Documentation Index Fetch the complete documentation index at: https://mintlify.com/aidenybai/react-grab/llms.txt
Use this file to discover all available pages before exploring further.
Overview
React Grab supports two activation modes that control how you enter and exit inspection mode:
Toggle mode (default) - Press once to activate, press again to deactivate
Hold mode - Hold the key to activate, release to deactivate
Activation Modes
Toggle Mode
In toggle mode, a single keypress activates React Grab and it stays active until you press the key again.
{
activationMode : "toggle" // Default
}
Behavior:
Press ⌘C (Mac) or Ctrl+C (Windows/Linux) to activate
Inspection mode stays active until you:
Press the activation key again to deactivate
Successfully copy an element (optional auto-deactivate)
Press Escape
Use Cases:
Extended inspection sessions
Comparing multiple elements
Copying several elements in sequence
Keyboard-driven navigation with arrow keys
Hold Mode
In hold mode, React Grab activates only while you hold down the activation key.
{
activationMode : "hold" ,
keyHoldDuration : 100 // milliseconds before activation
}
Behavior:
Press and hold the activation key for keyHoldDuration milliseconds
Inspection mode activates while key is held
Release the key to immediately deactivate
Implementation:
const DEFAULT_KEY_HOLD_DURATION_MS = 100 ;
let holdTimerId : number | null = null ;
let holdStartTimestamp : number | null = null ;
createEffect (() => {
if ( store . current . state !== "holding" ) {
clearHoldTimer ();
return ;
}
holdStartTimestamp = Date . now ();
holdTimerId = window . setTimeout (() => {
holdTimerId = null ;
actions . activate ();
}, store . keyHoldDuration );
onCleanup ( clearHoldTimer );
});
The system enters “holding” state on keydown, then transitions to “active” after the hold duration expires. On keyup, it immediately deactivates.
Use Cases:
Quick one-off inspections
Preventing accidental activation
Muscle memory from DevTools (inspect-on-hover)
Minimal interference with normal keyboard shortcuts
Keyboard Shortcuts
Default Activation Key
By default, React Grab uses the native copy shortcut:
Mac : ⌘C (Command+C)
Windows/Linux : Ctrl+C
The implementation detects the platform:
const isMac = () =>
typeof navigator !== "undefined" &&
/Mac | iPhone | iPod | iPad/ . test ( navigator . platform );
const defaultActivationKey = ( event : KeyboardEvent ) => {
const targetKey = event . code === "KeyC" || event . key === "c" ;
const hasModifier = isMac () ? event . metaKey : event . ctrlKey ;
const noOtherModifiers = ! event . shiftKey && ! event . altKey ;
return targetKey && hasModifier && noOtherModifiers ;
};
Copy Protection
When activated via the copy shortcut, React Grab prevents the default browser copy action:
if ( isTargetKeyCombination ( event , activationKey )) {
event . preventDefault ();
event . stopPropagation ();
if ( activationMode === "toggle" ) {
toggleActivate ();
} else {
actions . setHolding ();
}
}
Context-Aware Activation
React Grab intelligently handles activation inside inputs:
const allowActivationInsideInput = true ; // Default
if ( ! allowActivationInsideInput && isKeyboardEventTriggeredByInput ( event )) {
return ; // Don't activate
}
// Allow activation after a delay if user is focused in input
if ( hasTextSelectionInInput ()) {
setTimeout (() => {
if ( isActivationKeyPressed ()) {
activate ();
}
}, INPUT_TEXT_SELECTION_ACTIVATION_DELAY_MS ); // 600ms
}
Constants used:
const INPUT_FOCUS_ACTIVATION_DELAY_MS = 400 ;
const INPUT_TEXT_SELECTION_ACTIVATION_DELAY_MS = 600 ;
Additional Shortcuts
When React Grab is active:
Shortcut Action Escape Deactivate and exit inspection mode Arrow Keys Navigate between parent/child/sibling elements Enter Copy the currently selected element Right Click Open context menu with actions
Activation Key Customization
You can customize the activation key using the activationKey option:
{
activationKey : "KeyI" // Press 'I' key
}
Custom Function
For complex key combinations:
{
activationKey : ( event : KeyboardEvent ) => {
// Activate with Shift+Alt+I
return event . code === "KeyI" &&
event . shiftKey &&
event . altKey &&
! event . metaKey &&
! event . ctrlKey ;
}
}
Examples
Single key:
{ activationKey : "KeyG" } // Press 'G'
With modifiers:
{
activationKey : ( event ) =>
event . code === "KeyI" &&
( event . metaKey || event . ctrlKey ) &&
event . shiftKey
} // ⌘⇧I or Ctrl+Shift+I
Function key:
{ activationKey : "F12" } // Press F12
Parsing Activation Keys
Internally, React Grab parses activation keys:
const parseActivationKey = (
activationKey : ActivationKey | undefined
): (( event : KeyboardEvent ) => boolean ) => {
if ( ! activationKey ) {
return defaultActivationKey ;
}
if ( typeof activationKey === "function" ) {
return activationKey ;
}
// String format - match key code
return ( event : KeyboardEvent ) => event . code === activationKey ;
};
Hold Duration Configuration
The keyHoldDuration option controls how long you must hold the key before activation:
{
activationMode : "hold" ,
keyHoldDuration : 150 // milliseconds
}
Recommended values:
100ms (default) - Quick activation, minimal delay
200ms - More deliberate, prevents accidental activation
50ms - Very responsive, may activate unintentionally
Implementation Details
const DEFAULT_KEY_HOLD_DURATION_MS = 100 ;
const { store , actions } = createGrabStore ({
keyHoldDuration:
options . keyHoldDuration ??
DEFAULT_KEY_HOLD_DURATION_MS ,
});
The hold timer prevents activation from brief keypresses (like double-tapping copy):
// After copy operation completes
const MIN_HOLD_FOR_ACTIVATION_AFTER_COPY_MS = 200 ;
if ( holdDuration < MIN_HOLD_FOR_ACTIVATION_AFTER_COPY_MS ) {
// Too short - ignore
return ;
}
State Transitions
The activation state machine:
type ActivationState =
| "idle" // Not active, waiting for input
| "holding" // Key pressed (hold mode only)
| "active" // Inspection mode active
| "copying" // Copy in progress
| "justCopied" ; // Brief feedback state
Toggle mode transitions:
idle → (keydown) → active → (keydown again) → idle
↓ ↓
(copy) (copy)
↓ ↓
copying → justCopied → active or idle
Hold mode transitions:
idle → (keydown) → holding → (timer) → active → (keyup) → idle
↓ ↓
(keyup early) (copy)
↓ ↓
idle copying → justCopied → idle
The floating toolbar provides a visual toggle:
interface ToolbarState {
edge : "top" | "bottom" | "left" | "right" ;
ratio : number ; // Position along edge (0-1)
collapsed : boolean ; // Minimized state
enabled : boolean ; // Master on/off switch
}
Clicking the toolbar toggle activates in toggle mode regardless of the configured activationMode:
const handleToolbarToggle = () => {
actions . setWasActivatedByToggle ( true );
activateRenderer ();
};
Best Practices
Toggle mode is ideal when:
You’re inspecting multiple elements in sequence
You want to use arrow keys to navigate the component tree
You’re comparing elements across different parts of the UI
You want inspection mode to persist while you scroll or switch windows
Example: Debugging a complex layout with nested components
Hold mode is ideal when:
You want minimal interference with keyboard shortcuts
You prefer inspect-on-demand behavior
You’re making quick one-off inspections
You want to prevent accidental activation
Example: Quickly checking a single component’s source location
Customizing for your workflow
Combine activation mode with other options for optimal workflow: // Quick inspection with custom key
{
activationMode : "hold" ,
keyHoldDuration : 150 ,
activationKey : "KeyI"
}
// Extended inspection with auto-deactivate
{
activationMode : "toggle" ,
activationKey : ( e ) => e . code === "KeyG" && e . metaKey
}
Configuration Examples
Default Configuration
import { init } from "react-grab" ;
init ({
activationMode: "toggle" ,
keyHoldDuration: 100 ,
allowActivationInsideInput: true ,
});
Hold Mode with Custom Key
init ({
activationMode: "hold" ,
keyHoldDuration: 200 ,
activationKey: "KeyI" , // Press and hold 'I'
});
Toggle Mode with Function Key
init ({
activationMode: "toggle" ,
activationKey: "F9" , // Press F9 to toggle
});
Custom Modifier Combination
init ({
activationMode: "toggle" ,
activationKey : ( event ) => {
return (
event . code === "KeyE" &&
event . altKey &&
event . shiftKey &&
! event . metaKey &&
! event . ctrlKey
);
},
});