feat: add global keyboard shortcuts for undo/redo and command palette

This commit is contained in:
Your Name
2026-02-15 19:13:36 +02:00
parent e9318df6f6
commit 491c089be6
2 changed files with 60 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
import { useEffect } from "react";
import { useBoardStore } from "@/stores/board-store";
function isInputFocused(): boolean {
const el = document.activeElement;
if (!el) return false;
const tag = el.tagName.toLowerCase();
return (
tag === "input" ||
tag === "textarea" ||
(el as HTMLElement).isContentEditable
);
}
export function useKeyboardShortcuts(): void {
useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
const ctrl = e.ctrlKey || e.metaKey;
// Ctrl+K: open command palette (always works, even in inputs)
if (ctrl && e.key === "k") {
e.preventDefault();
document.dispatchEvent(new CustomEvent("open-command-palette"));
return;
}
// Skip remaining shortcuts when an input is focused
if (isInputFocused()) return;
// Ctrl+Shift+Z: redo
if (ctrl && e.shiftKey && e.key === "Z") {
e.preventDefault();
useBoardStore.temporal.getState().redo();
return;
}
// Ctrl+Z: undo
if (ctrl && e.key === "z") {
e.preventDefault();
useBoardStore.temporal.getState().undo();
return;
}
// Escape: close any open modal/dialog
// Note: Radix dialogs handle their own Escape, but this covers custom modals
if (e.key === "Escape") {
document.dispatchEvent(new CustomEvent("close-all-modals"));
return;
}
}
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, []);
}