diff --git a/.jules/palette.md b/.jules/palette.md new file mode 100644 index 00000000..8bf0327b --- /dev/null +++ b/.jules/palette.md @@ -0,0 +1,3 @@ +## 2024-05-27 - Duplicate Resume Modal Accessibility +**Learning:** Custom modals like `DuplicateResumeModal` require explicit ARIA attributes (`role="dialog"`, `aria-modal="true"`, `aria-labelledby`) and keyboard interactions (Escape key to close, backdrop click to close) to be fully accessible and provide a smooth user experience. +**Action:** When implementing custom modals, always include these standard accessibility and interaction patterns rather than just visual styling. diff --git a/resume-builder-ui/src/components/DuplicateResumeModal.tsx b/resume-builder-ui/src/components/DuplicateResumeModal.tsx index eacdfd6c..108e4901 100644 --- a/resume-builder-ui/src/components/DuplicateResumeModal.tsx +++ b/resume-builder-ui/src/components/DuplicateResumeModal.tsx @@ -24,6 +24,16 @@ export function DuplicateResumeModal({ } }, [resume]); + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape' && isOpen) { + onCancel(); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [isOpen, onCancel]); + if (!isOpen || !resume) return null; const handleSubmit = (e: React.FormEvent) => { @@ -34,8 +44,17 @@ export function DuplicateResumeModal({ }; return ( -
-
+
+
e.stopPropagation()} + role="dialog" + aria-modal="true" + aria-labelledby="duplicate-modal-title" + >
@@ -54,7 +73,7 @@ export function DuplicateResumeModal({
-

Duplicate Resume

+

Duplicate Resume

Create a copy with a new name