diff --git a/web/src/components/ShortcutsModal.tsx b/web/src/components/ShortcutsModal.tsx index ecd7b831..50697b0b 100644 --- a/web/src/components/ShortcutsModal.tsx +++ b/web/src/components/ShortcutsModal.tsx @@ -1,7 +1,6 @@ -import { useEffect } from 'react'; -import { X } from 'lucide-react'; import { useUIStore } from '../stores/uiStore'; import { formatCombo, type ShortcutCombo } from '../utils/keyboard'; +import { Modal } from './ui/Modal'; interface DisplayShortcut { combo: ShortcutCombo; @@ -51,65 +50,31 @@ export function ShortcutsModal() { const open = useUIStore((s) => s.shortcutsModalOpen); const close = useUIStore((s) => s.closeShortcutsModal); - // Local Esc handler — runs *before* the document-level shortcut listeners - // because modal mount captures it first when focus is inside. - useEffect(() => { - if (!open) return; - const onKey = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - e.preventDefault(); - e.stopPropagation(); - close(); - } - }; - document.addEventListener('keydown', onKey, true); // capture phase = wins - return () => document.removeEventListener('keydown', onKey, true); - }, [open, close]); - - if (!open) return null; - + // The capture-phase Escape handling this component used to own is now + // the Modal's job, along with the focus trap it never had. return ( -
-
e.stopPropagation()} - > -
-

Keyboard shortcuts

- -
- -
- {SECTIONS.map((section) => ( -
-

- {section.title} -

-
- {section.items.map((item, idx) => ( -
- {item.description} - -
- ))} -
+ +
+ {SECTIONS.map((section) => ( +
+

+ {section.title} +

+
+ {section.items.map((item, idx) => ( +
+ {item.description} + +
+ ))}
- ))} -
+
+ ))}
-
+ ); } diff --git a/web/src/components/Tasks/TaskCreateDialog.tsx b/web/src/components/Tasks/TaskCreateDialog.tsx index 37de8333..e560d225 100644 --- a/web/src/components/Tasks/TaskCreateDialog.tsx +++ b/web/src/components/Tasks/TaskCreateDialog.tsx @@ -1,5 +1,7 @@ import { useState } from 'react'; -import { X } from 'lucide-react'; +import { Modal } from '../ui/Modal'; + +const FORM_ID = 'task-create-form'; export function TaskCreateDialog({ onClose, onCreate }: { onClose: () => void; @@ -16,55 +18,63 @@ export function TaskCreateDialog({ onClose, onCreate }: { }; return ( -
-
e.stopPropagation()}> -
-

New Task

- + {/* Outside the
, associated by id — keeps the button in the + modal's footer slot while Enter-to-submit still works. */} + + + } + > + +
+ + setTitle(e.target.value)} + autoFocus + className="w-full px-3 py-2 bg-surface-raised border border-border-subtle rounded-lg text-[14px] text-text outline-none focus:border-accent/50" + /> +
+
+ +