🎨 Palette: Improve DuplicateResumeModal accessibility and interaction#533
🎨 Palette: Improve DuplicateResumeModal accessibility and interaction#533aafre wants to merge 1 commit into
Conversation
Added backdrop click handling, Escape key support, ARIA attributes, and explicit keyboard focus outlines to DuplicateResumeModal for improved accessibility. Co-authored-by: aafre <8656674+aafre@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Code Review
This pull request improves the accessibility of the DuplicateResumeModal by implementing Escape key support, backdrop click-to-close functionality, and standard ARIA attributes. It also updates the .Jules/palette.md documentation to include these accessibility practices. Feedback focuses on optimizing the event listener attachment to trigger only when the modal is open, implementing a mandatory focus trap for the modal as per repository rules, and ensuring the documentation reflects this focus trap requirement.
| <div | ||
| className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4" | ||
| onClick={(e) => e.stopPropagation()} | ||
| role="dialog" | ||
| aria-modal="true" | ||
| aria-labelledby="duplicate-modal-title" | ||
| > |
There was a problem hiding this comment.
While the modal now includes several accessibility improvements, it is missing a focus trap. According to the repository's general rules, all modals must implement a focus trap to ensure keyboard focus remains within the modal's focusable elements while it is open. This prevents users from accidentally tabbing out of the modal into the background content.
References
- For accessibility, all modals must implement a focus trap to ensure keyboard focus remains within the modal's focusable elements while it is open.
| useEffect(() => { | ||
| const handleKeyDown = (e: KeyboardEvent) => { | ||
| if (e.key === 'Escape' && isOpen && !isDuplicating) { | ||
| onCancel(); | ||
| } | ||
| }; | ||
|
|
||
| window.addEventListener('keydown', handleKeyDown); | ||
| return () => window.removeEventListener('keydown', handleKeyDown); | ||
| }, [isOpen, isDuplicating, onCancel]); |
There was a problem hiding this comment.
The keydown event listener is currently attached to the window as soon as the component is mounted, even if the modal is not open. It's more efficient to only attach the listener when isOpen is true. This also allows removing the redundant isOpen check inside the handler.
| useEffect(() => { | |
| const handleKeyDown = (e: KeyboardEvent) => { | |
| if (e.key === 'Escape' && isOpen && !isDuplicating) { | |
| onCancel(); | |
| } | |
| }; | |
| window.addEventListener('keydown', handleKeyDown); | |
| return () => window.removeEventListener('keydown', handleKeyDown); | |
| }, [isOpen, isDuplicating, onCancel]); | |
| useEffect(() => { | |
| if (!isOpen) return; | |
| const handleKeyDown = (e: KeyboardEvent) => { | |
| if (e.key === 'Escape' && !isDuplicating) { | |
| onCancel(); | |
| } | |
| }; | |
| window.addEventListener('keydown', handleKeyDown); | |
| return () => window.removeEventListener('keydown', handleKeyDown); | |
| }, [isOpen, isDuplicating, onCancel]); |
| **Action:** Always use `ResponsiveConfirmDialog` for destructive confirmation prompts (such as `DeleteResumeModal`) to ensure a consistent, accessible, and mobile-friendly UX that prevents accidental data loss. | ||
| ## 2024-05-15 - DuplicateResumeModal Accessibility Enhancement | ||
| **Learning:** Custom modals like DuplicateResumeModal often lack basic interactive backdrop close handling, keyboard handlers, ARIA roles, and keyboard navigation outline visibility, which impairs accessibility. | ||
| **Action:** When creating or modifying custom modals, ensure `onClick` handlers for the backdrop correctly ignore inner modal clicks (via `stopPropagation`), handle the `Escape` key, assign `role="dialog"`, use `aria-modal="true"`, link titles via `aria-labelledby`, add `aria-hidden` to decorative items, and add explicit `focus-visible` outline styles to buttons. |
There was a problem hiding this comment.
The action item for custom modals should include the requirement for a focus trap, as specified in the repository's general rules.
| **Action:** When creating or modifying custom modals, ensure `onClick` handlers for the backdrop correctly ignore inner modal clicks (via `stopPropagation`), handle the `Escape` key, assign `role="dialog"`, use `aria-modal="true"`, link titles via `aria-labelledby`, add `aria-hidden` to decorative items, and add explicit `focus-visible` outline styles to buttons. | |
| Action: When creating or modifying custom modals, ensure they implement a focus trap, onClick handlers for the backdrop correctly ignore inner modal clicks (via stopPropagation), handle the Escape key, assign role="dialog", use aria-modal="true", link titles via aria-labelledby, add aria-hidden to decorative items, and add explicit focus-visible outline styles to buttons. |
References
- For accessibility, all modals must implement a focus trap to ensure keyboard focus remains within the modal's focusable elements while it is open.
- Ensure documentation, such as testing plans, is updated to reflect UI and implementation changes made in the same pull request.
💡 What:
Added accessibility and interaction improvements to the
DuplicateResumeModal. This includes backdrop click to close, Escape key support, ARIA roles, and proper focus ring visibility for buttons.🎯 Why:
The modal previously required users to explicitly click the "Cancel" button to close it, which was not intuitive. It also lacked necessary ARIA attributes for screen readers and did not clearly indicate focus state for keyboard navigation.
📸 Before/After:
Visually similar, but buttons now show a distinct outline when focused via keyboard, and the modal can be closed by clicking the backdrop or pressing the Escape key.
♿ Accessibility:
role="dialog",aria-modal="true", andaria-labelledbyto the modal container.h2with thearia-labelledbyID.aria-hidden="true"to the decorative SVG icon.focus-visible:ring-2 focus-visible:ring-offset-2classes to the "Duplicate" and "Cancel" buttons.Escapekey event listener for quick closing.PR created automatically by Jules for task 13457695637123231205 started by @aafre