← Back to all hooks

useKeyPress / useKeyboardShortcut

Detect key presses and keyboard shortcuts with modifier keys. Perfect for hotkeys and accessibility.

Live Demo

🎮 Score

0

Use keyboard shortcuts to earn points!

⬆️ Arrow Keys

🎮 WASD Keys

W
A
S
D

⌨️ Special Keys

Space
Enter
Esc

⌨️ Try These Shortcuts

Cmd+SSave (+10 points)
Cmd+KSearch (+10 points)
Cmd+Shift+PPrint (+10 points)
Cmd+ZUndo (-5 points)

📝 Event Log

No shortcuts used yet. Try pressing Cmd+S!

💡 Try This:

  • Press arrow keys or WASD to see them light up
  • Try special keys like Space, Enter, and Escape
  • Use keyboard shortcuts to earn points
  • On Mac use Cmd, on Windows/Linux use Ctrl

Code Examples

Basic Key Detection

import { useKeyPress } from "@uiblock/hooks";

function Game() {
  const wPressed = useKeyPress('w');
  const aPressed = useKeyPress('a');
  const sPressed = useKeyPress('s');
  const dPressed = useKeyPress('d');

  return (
    <div>
      <p>W: {wPressed ? '⬆️' : '⬜'}</p>
      <p>A: {aPressed ? '⬅️' : '⬜'}</p>
      <p>S: {sPressed ? '⬇️' : '⬜'}</p>
      <p>D: {dPressed ? '➡️' : '⬜'}</p>
    </div>
  );
}

Keyboard Shortcuts

import { useKeyboardShortcut } from "@uiblock/hooks";

function Editor() {
  // Cmd/Ctrl + S to save
  useKeyboardShortcut(
    { key: 's', meta: true },
    () => console.log('Save!')
  );

  // Cmd/Ctrl + K to open command palette
  useKeyboardShortcut(
    { key: 'k', meta: true },
    () => console.log('Command palette')
  );

  // Cmd/Ctrl + Shift + P
  useKeyboardShortcut(
    { key: 'p', meta: true, shift: true },
    () => console.log('Print')
  );

  return <div>Editor with shortcuts</div>;
}

With Options

import { useKeyPress, useKeyboardShortcut } from "@uiblock/hooks";

function Component() {
  const [enabled, setEnabled] = useState(true);

  // Conditional key press
  const spacePressed = useKeyPress('Space', {
    enabled,
    eventType: 'keydown'
  });

  // Don't prevent default
  useKeyboardShortcut(
    { key: 'Enter' },
    () => console.log('Enter pressed'),
    { preventDefault: false }
  );

  return <div>Component</div>;
}

How It Works

Here's the implementation:

import { useEffect, useState, useRef } from 'react'

// useKeyPress - Detect when a specific key is pressed
export function useKeyPress(targetKey, options = {}) {
  const { target, eventType = 'keydown', enabled = true } = options
  const [keyPressed, setKeyPressed] = useState(false)

  useEffect(() => {
    if (!enabled) return

    const downHandler = (event) => {
      if (event.key === targetKey) {
        setKeyPressed(true)
      }
    }

    const upHandler = (event) => {
      if (event.key === targetKey) {
        setKeyPressed(false)
      }
    }

    const targetElement = target?.current ?? window

    if (eventType === 'keydown') {
      targetElement.addEventListener('keydown', downHandler)
      targetElement.addEventListener('keyup', upHandler)
    } else {
      targetElement.addEventListener('keyup', downHandler)
    }

    return () => {
      targetElement.removeEventListener('keydown', downHandler)
      targetElement.removeEventListener('keyup', upHandler)
    }
  }, [targetKey, target, eventType, enabled])

  return keyPressed
}

// useKeyboardShortcut - Detect keyboard shortcuts with modifiers
export function useKeyboardShortcut(shortcut, callback, options = {}) {
  const { enabled = true, preventDefault = true, eventType = 'keydown' } = options
  const savedCallback = useRef(callback)

  useEffect(() => {
    savedCallback.current = callback
  }, [callback])

  useEffect(() => {
    if (!enabled) return

    const handler = (event) => {
      const { key, ctrl = false, shift = false, alt = false, meta = false } = shortcut

      const isMatch =
        event.key.toLowerCase() === key.toLowerCase() &&
        event.ctrlKey === ctrl &&
        event.shiftKey === shift &&
        event.altKey === alt &&
        event.metaKey === meta

      if (isMatch) {
        if (preventDefault) {
          event.preventDefault()
        }
        savedCallback.current(event)
      }
    }

    window.addEventListener(eventType, handler)

    return () => {
      window.removeEventListener(eventType, handler)
    }
  }, [shortcut, enabled, preventDefault, eventType])
}

Key Features:

  • Detects single key presses with state tracking
  • Supports keyboard shortcuts with modifier keys (Ctrl, Shift, Alt, Meta)
  • Configurable event types and preventDefault
  • Stable callback reference with useRef

API Reference

useKeyPress

targetKey: string

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

options?: UseKeyPressOptions

target, eventType, enabled

returns: boolean

Whether the key is currently pressed

useKeyboardShortcut

shortcut: KeyboardShortcut

Object with key, ctrl, shift, alt, meta properties

callback: (event) => void

Function to call when shortcut is pressed

options?: UseKeyboardShortcutOptions

enabled, preventDefault, eventType

💡 Use Cases

  • Game controls (WASD, arrow keys)
  • Editor shortcuts (save, undo, redo)
  • Modal controls (Escape to close)
  • Navigation shortcuts
  • Accessibility features
  • Form submission (Enter key)