Input
Hooks for keyboard shortcuts, held-key state, idle detection, gamepads, user-activation gating, and Pointer Lock — everything short of full drag/drop or touch gesture handling (see DOM / Element Interaction for those).
useKeyPress
Tracks whether any of the given key(s) is currently held down, matching KeyboardEvent.key case-insensitively via keydown/keyup on window. SSR-safe — returns false until the client subscribes.
const isShiftHeld = useKeyPress("Shift");
const isArrowHeld = useKeyPress(["ArrowLeft", "ArrowRight"]);useHotkeys
Registers "ctrl+s"-style keyboard shortcut combos mapped to handlers, matched on keydown against window. Modifiers (ctrl/control, shift, alt, meta/cmd/command) must all match exactly — a plain "s" binding never fires while ctrl is held.
useHotkeys({ "ctrl+s": save, "shift+enter": submit }, { preventDefault: true });useIdle
true once a timeout (default 60s) has passed without user activity — mouse move/click, key press, touch, scroll, or wheel — resetting to false on the next activity. SSR-safe — returns false on the server and until the first timeout elapses on the client.
const isIdle = useIdle(5 * 60_000); // idle after 5 minutesuseGamepad
Currently connected gamepads, via the Gamepad API's navigator.getGamepads(), updating on gamepadconnected/gamepaddisconnected. Only exposes id/index/mapping — live button/axis state requires polling on an animation frame, out of scope for this hook.
const gamepads = useGamepad();
const isControllerConnected = gamepads.length > 0;useUserActivation
Wraps navigator.userActivation — whether the page has ever/is currently within a user-activation window (a click, key press, or similar gesture) — useful to gate autoplay/popups browsers block outside one. Falls back to { isActive: false, hasBeenActive: false } during server rendering and where the API is unsupported.
const { isActive } = useUserActivation();
if (isActive) audio.play(); // gate autoplay behind a real user gestureusePointerLock
Wraps the Pointer Lock API for a single ref'd element — attach ref to the element (e.g. a <canvas>) that should capture the pointer, then call request()/exit() imperatively, typically from a click handler (the API requires a user gesture). supported: false is the SSR-safe default where the API doesn't exist.
const { ref, locked, request, exit } = usePointerLock<HTMLCanvasElement>();
return <canvas ref={ref} onClick={() => request()} />;