useKeyPress

UI/Interaction

A React hook that detects keyboard interactions, perfect for shortcuts and keyboard-driven interfaces.

Demo

Press any of these keys to see them highlight:

Space
Enter
Escape
A

Note: Make sure this window has focus for the key detection to work.

Installation

npm install @thibault.sh/hooks

Usage

import { useKeyPress } from '@thibault.sh/hooks/useKeyPress';

function ShortcutHandler() {
  const isSPressed = useKeyPress('s');
  const isCtrlPressed = useKeyPress('Control');

  // Save when Ctrl+S is pressed
  React.useEffect(() => {
    if (isSPressed && isCtrlPressed) {
      handleSave();
    }
  }, [isSPressed, isCtrlPressed]);

  return (
    <div>
      <p>Press Ctrl+S to save</p>
      {isSPressed && isCtrlPressed && (
        <div>Saving...</div>
      )}
    </div>
  );
}

API

Parameters

  • targetKey
    string

    The key to detect (e.g., "Enter", "Escape", "a")

Returns

{boolean} Boolean indicating if the key is currently pressed

Key Names:

  • • Single characters: "a", "b", "1", "2", " " (space)
  • • Special keys: "Enter", "Escape", "Tab", "Backspace", "Delete"
  • • Modifier keys: "Control", "Shift", "Alt", "Meta"
  • • Arrow keys: "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"

Features

  • Real-time Detection

    Instantly detects key press and release events

  • Multiple Keys

    Track multiple keys simultaneously for complex shortcuts

  • Cleanup

    Automatically removes event listeners when component unmounts

  • Type Safety

    Full TypeScript support for key names

Modal Example

import { useKeyPress } from '@thibault.sh/hooks';
import { useState } from 'react';

function ModalWithKeyboard() {
  const [isOpen, setIsOpen] = useState(false);
  const isEscapePressed = useKeyPress('Escape');

  // Close modal when Escape is pressed
  React.useEffect(() => {
    if (isEscapePressed && isOpen) {
      setIsOpen(false);
    }
  }, [isEscapePressed, isOpen]);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>
        Open Modal (Press Escape to close)
      </button>

      {isOpen && (
        <div className="modal">
          <div className="modal-content">
            <h2>Modal Content</h2>
            <p>Press Escape to close this modal</p>
            <button onClick={() => setIsOpen(false)}>
              Close
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

Game Controls Example

import { useKeyPress } from '@thibault.sh/hooks';
import { useState } from 'react';

interface Position {
  x: number;
  y: number;
}

function SimpleGame() {
  const [position, setPosition] = useState<Position>({ x: 0, y: 0 });
  
  const isUpPressed = useKeyPress('ArrowUp');
  const isDownPressed = useKeyPress('ArrowDown');
  const isLeftPressed = useKeyPress('ArrowLeft');
  const isRightPressed = useKeyPress('ArrowRight');
  const isSpacePressed = useKeyPress(' ');

  // Update position based on arrow keys
  React.useEffect(() => {
    const speed = 5;
    if (isUpPressed) {
      setPosition(prev => ({ ...prev, y: prev.y - speed }));
    }
    if (isDownPressed) {
      setPosition(prev => ({ ...prev, y: prev.y + speed }));
    }
    if (isLeftPressed) {
      setPosition(prev => ({ ...prev, x: prev.x - speed }));
    }
    if (isRightPressed) {
      setPosition(prev => ({ ...prev, x: prev.x + speed }));
    }
  }, [isUpPressed, isDownPressed, isLeftPressed, isRightPressed]);

  return (
    <div className="game-container">
      <div
        className="player"
        style={{
          transform: `translate(${position.x}px, ${position.y}px)`,
          backgroundColor: isSpacePressed ? 'red' : 'blue'
        }}
      />
      <div className="instructions">
        <p>Use arrow keys to move</p>
        <p>Hold space to change color</p>
      </div>
    </div>
  );
}