tftsr-devops_investigation/src/hooks/useKeyboardShortcuts.ts
Shaun Arman f7b4e591f9 fix(performance): resolve memory leaks and add polish features
- Fix LogStreamPanel event listener cleanup with synchronous unlisten
- Fix eventBus async-unsafe unsubscribe with proper error handling
- Fix KubernetesPage infinite loading by resetting state on section change
- Add ErrorBoundary component with reset capability
- Add Badge component with multiple variants
- Add ResourceDetailsDrawer for slide-out details panel
- Add useFavorites hook with localStorage persistence
- Add useKeyboardShortcuts hook for declarative shortcuts
- Add comprehensive test coverage for all new components/hooks
- Add keyboard shortcuts documentation to README
- Wrap KubernetesPage with ErrorBoundary for crash recovery
- Install react-window for virtual scrolling support

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 13:28:30 -05:00

56 lines
1.9 KiB
TypeScript

import { useEffect, useCallback, useRef } from "react";
export interface KeyboardShortcut {
key: string;
ctrl?: boolean;
alt?: boolean;
shift?: boolean;
meta?: boolean;
callback: () => void;
description: string;
enabled?: boolean;
}
export function useKeyboardShortcuts(shortcuts: KeyboardShortcut[]): void {
const shortcutsRef = useRef(shortcuts);
shortcutsRef.current = shortcuts;
const handleKeyDown = useCallback((event: KeyboardEvent) => {
for (const shortcut of shortcutsRef.current) {
if (shortcut.enabled === false) continue;
const ctrlMatch = shortcut.ctrl ? event.ctrlKey || event.metaKey : !event.ctrlKey && !event.metaKey;
const altMatch = shortcut.alt ? event.altKey : !event.altKey;
const shiftMatch = shortcut.shift ? event.shiftKey : !event.shiftKey;
const metaMatch = shortcut.meta ? event.metaKey : !event.metaKey;
if (
event.key.toLowerCase() === shortcut.key.toLowerCase() &&
ctrlMatch &&
altMatch &&
shiftMatch &&
metaMatch
) {
event.preventDefault();
shortcut.callback();
break;
}
}
}, []);
useEffect(() => {
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [handleKeyDown]);
}
export const GLOBAL_SHORTCUTS = {
COMMAND_PALETTE: { key: "k", ctrl: true, description: "Open command palette" },
REFRESH: { key: "r", ctrl: true, description: "Refresh current view" },
SEARCH: { key: "f", ctrl: true, description: "Focus search" },
HELP: { key: "?", shift: true, description: "Show keyboard shortcuts" },
ESCAPE: { key: "Escape", description: "Close modal/dialog" },
NAVIGATE_UP: { key: "ArrowUp", ctrl: true, description: "Navigate up" },
NAVIGATE_DOWN: { key: "ArrowDown", ctrl: true, description: "Navigate down" },
} as const;