just-hotkeys

A declarative keyboard shortcut manager for JavaScript and TypeScript

Search Modal

Open search with Cmd+K, close with Escape

import { useState } from 'react';
import { useShortcuts } from 'just-hotkeys/react';

function SearchModal() {
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');

  useShortcuts({
    'cmd+k': () => setOpen(true),
    esc: () => setOpen(false),
  });

  return open ? (
    <div className="modal">
      <input
        value={query}
        onChange={e => setQuery(e.target.value)}
        placeholder="Search..."
        autoFocus
      />
    </div>
  ) : null;
}

Command Palette

Open command palette with Cmd+Shift+P

import { useState } from 'react';
import { useShortcuts } from 'just-hotkeys/react';

function CommandPalette() {
  const [open, setOpen] = useState(false);
  
  const newFile = () => console.log('Creating new file...');
  const openFile = () => console.log('Opening file...');
  const saveAs = () => console.log('Saving file as...');
  
  const commands = [
    { key: 'cmd+shift+n', label: 'New File', action: newFile },
    { key: 'cmd+shift+o', label: 'Open File', action: openFile },
    { key: 'cmd+shift+s', label: 'Save As', action: saveAs },
  ];

  useShortcuts({
    'cmd+shift+p': () => setOpen(true),
    esc: () => setOpen(false),
    ...commands.reduce((acc, cmd) => ({
      ...acc,
      [cmd.key]: cmd.action,
    }), {})
  });

  return open ? (
    <div className="command-palette">
      {commands.map(cmd => (
        <div key={cmd.key} className="command">
          <span className="shortcut">{cmd.key}</span>
          <span className="label">{cmd.label}</span>
        </div>
      ))}
    </div>
  ) : null;
}

Navigation Controls

Arrow keys with modifiers for navigation

import { useState, useRef } from 'react';
import { useShortcuts } from 'just-hotkeys/react';

function NavigationComponent() {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const panelRef = useRef(null);

  const jump = () => console.log('Jumping!');

  useShortcuts({
    'arrowup': () => setPosition(p => ({ ...p, y: p.y - 1 })),
    'arrowdown': () => setPosition(p => ({ ...p, y: p.y + 1 })),
    'arrowleft': () => setPosition(p => ({ ...p, x: p.x - 1 })),
    'arrowright': () => setPosition(p => ({ ...p, x: p.x + 1 })),
    'shift+arrowup': () => setPosition(p => ({ ...p, y: p.y - 10 })),
    'shift+arrowdown': () => setPosition(p => ({ ...p, y: p.y + 10 })),
    'cmd+arrowup': () => setPosition(p => ({ ...p, y: 0 })),
    'cmd+arrowdown': () => setPosition(p => ({ ...p, y: 100 })),
  });

  return <div ref={panelRef} style={{ left: position.x, top: position.y }}>Player</div>;
}

Install

npm install just-hotkeys