🎨 Palette: [UX improvement] Improve ProjectUpload accessibility#82
Conversation
- Added Escape key support to close the modal.
- Made the file drop zone keyboard-accessible by adding role="button", tabIndex={0}, and an onKeyDown handler for Enter/Space keys.
- Prevented the nested inner "Select Folder" button from double-focusing.
- Added aria-live="polite" and aria-busy="true" to the "Analyzing Project..." state for screen reader announcements.
|
👋 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. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
This PR improves the accessibility and keyboard usability of the ProjectUpload modal in the explorer UI, targeting keyboard-only navigation and screen reader announcements during the analysis/upload flow.
Changes:
- Added a global Escape key listener to close the upload modal (when not analyzing).
- Made the upload drop-zone keyboard-focusable and activatable via Enter/Space, with ARIA labeling.
- Improved screen reader behavior for the analyzing state (live region + spinner hidden from AT).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const handleKeyDown = (e) => { | ||
| if (e.key === 'Escape' && isModalOpen && !isAnalyzing) { | ||
| setIsModalOpen(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
The Escape key handler is attached to window unconditionally, which means it will fire alongside other global Escape listeners (e.g., SearchBar closes and clears on Escape). When the upload modal is open, pressing Escape will likely clear the search state in the background as well. Consider only registering the listener while the modal is open and/or handling Escape at the modal level (so it doesn’t interfere with unrelated global shortcuts).
| const handleKeyDown = (e) => { | |
| if (e.key === 'Escape' && isModalOpen && !isAnalyzing) { | |
| setIsModalOpen(false); | |
| } | |
| }; | |
| // Only attach the Escape handler while the modal is open and not analyzing | |
| if (!isModalOpen || isAnalyzing) { | |
| return; | |
| } | |
| const handleKeyDown = (e) => { | |
| if (e.key === 'Escape') { | |
| setIsModalOpen(false); | |
| } | |
| }; |
| multiple | ||
| /> | ||
| <button className="upload-select-btn">Select Folder</button> | ||
| <button className="upload-select-btn" tabIndex={-1} aria-hidden="true">Select Folder</button> |
There was a problem hiding this comment.
aria-hidden="true" is applied to an interactive <button>. Even with tabIndex={-1}, this is still clickable and can be programmatically focused, which conflicts with WAI-ARIA guidance (hidden content shouldn’t be interactive). If the button is purely decorative, consider rendering a non-interactive element (e.g., <span>/<div>) styled like a button; if it’s meant to be interactive, it shouldn’t be aria-hidden and should remain keyboard-accessible.
| <button className="upload-select-btn" tabIndex={-1} aria-hidden="true">Select Folder</button> | |
| <span className="upload-select-btn">Select Folder</span> |
| onKeyDown={(e) => { | ||
| if (e.key === 'Enter' || e.key === ' ') { | ||
| e.preventDefault(); | ||
| fileInputRef.current?.click(); | ||
| } | ||
| }} |
There was a problem hiding this comment.
The keyboard handler checks for e.key === ' ' for Space. Some browsers / environments may report Space as 'Spacebar' (legacy) or you may prefer checking e.code === 'Space' for consistency. Expanding the check improves robustness of Space-to-activate behavior for the upload zone.
💡 What: Added full keyboard navigation support, ARIA states, and an Escape key listener to the
ProjectUploadmodal.🎯 Why: Previously, users relying on keyboard navigation could not easily trigger the upload file picker by tabbing to the drag-and-drop zone. Furthermore, the loading spinner was invisible to screen readers, and the modal lacked the standard Escape key functionality to close it.
📸 Before/After:
(UI visibly looks identical, improvements are invisible/semantic)
♿ Accessibility:
role="button"andtabIndex={0}to the.upload-zonedivto make it focusable.onKeyDownto handleEnterorSpacekey presses to trigger the file picker.aria-live="polite"andaria-busy="true"to the analyzing state to announce upload status.Escapekey logic to close the modal for better keyboard operation.PR created automatically by Jules for task 7728302375148618639 started by @madara88645