SCALE — Build Lab
開発パターン · REACT HOOK

キーボードショートカット管理

CATEGORY開発パターン TYPEReact Hook EFFORT60〜120分 DIFFICULTY
PRIMARY CODE
tsx
import { useEffect } from 'react';

type Shortcut = { keys: string; description: string; action: () => void };

export function useShortcuts(shortcuts: Shortcut[]) {
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      // フォーカス中の入力欄では無効
      const t = e.target as HTMLElement;
      if (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable) return;

      const key = e.key.toLowerCase();
      const mod = e.metaKey || e.ctrlKey;
      const shift = e.shiftKey;

      for (const s of shortcuts) {
        const parts = s.keys.toLowerCase().split('+');
        const wantMod = parts.includes('cmd') || parts.includes('ctrl');
        const wantShift = parts.includes('shift');
        const wantKey = parts.filter(p => !['cmd','ctrl','shift'].includes(p))[0];
        if (wantMod === mod && wantShift === shift && key === wantKey) {
          e.preventDefault();
          s.action();
          return;
        }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [shortcuts]);
}

// 使い方:
// useShortcuts([
//   { keys: 'cmd+k', description: '検索を開く', action: openSearch },
//   { keys: 'cmd+shift+n', description: '新規作成', action: createNew },
//   { keys: '?', description: 'ヘルプ', action: showHelp },
// ]);
前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 任意のダッシュボードに組み込み

キーボードショートカット管理

:LiTarget: 用途

⌘+K, ?, Esc 等のキー操作を集中管理。フォーカス中の入力欄では無効化。

:LiSparkle: 特徴

  • Cmd/Ctrl 修飾キー
  • シーケンス対応
  • INPUT 内では無効
  • チートシート自動生成

:LiCode: コード(コピペ用)

import { useEffect } from 'react';

type Shortcut = { keys: string; description: string; action: () => void };

export function useShortcuts(shortcuts: Shortcut[]) {
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      // フォーカス中の入力欄では無効
      const t = e.target as HTMLElement;
      if (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable) return;

      const key = e.key.toLowerCase();
      const mod = e.metaKey || e.ctrlKey;
      const shift = e.shiftKey;

      for (const s of shortcuts) {
        const parts = s.keys.toLowerCase().split('+');
        const wantMod = parts.includes('cmd') || parts.includes('ctrl');
        const wantShift = parts.includes('shift');
        const wantKey = parts.filter(p => !['cmd','ctrl','shift'].includes(p))[0];
        if (wantMod === mod && wantShift === shift && key === wantKey) {
          e.preventDefault();
          s.action();
          return;
        }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [shortcuts]);
}

// 使い方:
// useShortcuts([
//   { keys: 'cmd+k', description: '検索を開く', action: openSearch },
//   { keys: 'cmd+shift+n', description: '新規作成', action: createNew },
//   { keys: '?', description: 'ヘルプ', action: showHelp },
// ]);

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加