Image editor: improve media editor crop accessibility and dialog focus#78047
Conversation
- Added `aria-haspopup` attributes to image and site logo components to improve accessibility. - Implemented focus management for crop areas in the media editor, ensuring they receive focus on mount and provide keyboard navigation hints. - Updated confirm dialog to handle keyboard events more effectively, allowing for better user interaction. - Introduced aria descriptions for crop areas and resize handles to enhance screen reader support. These changes aim to improve the overall user experience and accessibility of the media editing features.
- Introduced a new `visually-hidden-style.ts` file containing CSS styles to visually hide elements while keeping them accessible to screen readers. - Replaced inline visually hidden styles in `cropper.tsx` and `rectangle-stencil.tsx` with imports from the new file to promote code reuse and maintainability. - Updated `use-aria-announcer.ts` to utilize the latest state reference for better performance and accuracy in announcements. These changes enhance the accessibility features of the media editor components, ensuring a better experience for users relying on assistive technologies.
- Implemented a keydown handler to return focus to the crop area when Shift+Tab is pressed on the first resize handle. - Added a corresponding test to verify the focus behavior during keyboard navigation. These changes enhance accessibility and improve the user experience for keyboard users in the media editor.
…essibility - Removed the onKeyDown prop and associated keyboard navigation logic from the ConfirmDialog component. - Simplified the key handling by directly using the handleEnter function for the modal's onKeyDown event. - Updated tests to remove unnecessary focus management checks, streamlining the test suite. These changes enhance the clarity and maintainability of the ConfirmDialog component while ensuring a better user experience for keyboard navigation.
…n CropperInner - Added an optional `onEscape` callback to the `StencilProps` interface to handle Escape key events. - Implemented the `handleStencilEscape` function in `CropperInner` to focus the canvas when Escape is pressed, enhancing keyboard navigation. These changes improve accessibility and user experience for keyboard users in the media editor.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
This PR improves keyboard and screen reader accessibility in the experimental media editor modal’s crop experience, focusing on clearer ARIA messaging and better focus management in the crop area and discard confirmation flow.
Changes:
- Adds focus-on-mount + improved ARIA descriptions for the crop area and resize handles, and adjusts Escape handling to allow modal-level discard behavior.
- Enhances ARIA-live announcements (including flip state) with i18n-safe strings and debounced deduping, plus new unit tests.
- Marks Crop toolbar actions as opening dialogs when the media editor modal flow is active.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/media-editor/src/image-editor/react/visually-hidden-style.ts | Introduces a shared visually-hidden inline style object for accessible hidden content. |
| packages/media-editor/src/image-editor/react/hooks/use-aria-announcer.ts | Adds i18n-safe announcements and flip-state-specific messaging with debouncing. |
| packages/media-editor/src/image-editor/react/hooks/test/use-aria-announcer.ts | Adds tests verifying flip announcements behavior. |
| packages/media-editor/src/image-editor/react/components/test/cropper.tsx | Updates and adds tests for crop-area labeling, focus-on-mount, and handle focus behavior. |
| packages/media-editor/src/image-editor/react/components/stencils/test/rectangle-stencil.tsx | Adds tests for handle descriptions and ensures Escape isn’t intercepted on handles. |
| packages/media-editor/src/image-editor/react/components/stencils/rectangle-stencil.tsx | Adds shared handle description via aria-describedby and removes Escape interception. |
| packages/media-editor/src/image-editor/core/types.ts | Removes onEscape from StencilProps to match new behavior. |
| packages/media-editor/src/components/media-editor-modal/index.tsx | Improves discard confirmation labeling/description wiring; passes focus-on-mount into the canvas. |
| packages/media-editor/src/components/media-editor-canvas/index.tsx | Plumbs focusOnMount through to the underlying cropper. |
| packages/block-library/src/site-logo/edit.js | Adds aria-haspopup="dialog" to Crop control when using the media editor modal. |
| packages/block-library/src/image/image.js | Adds aria-haspopup="dialog" to Crop control when using the media editor modal. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Introduced a new crop area element in the Cropper component to improve keyboard navigation and accessibility. - Updated focus handling to ensure the crop area receives focus on mount and when navigating with Shift+Tab. - Refactored tests to utilize the new crop area element and verify focus behavior, enhancing overall test coverage. These changes aim to provide a better user experience for keyboard users and improve accessibility in the media editor.
|
Thanks for looking into these! Just a quick comment on this one:
When we were working on the resize handles and keyboard behaviour for moving the cropper area we intentionally didn't bubble up so that keyboard users can smoothly transition between moving the crop handle, and moving the overall crop area. In this PR it feels too easy to accidentally close the cropper to me, and makes it harder to transition between the handles and moving the overall area. |
|
Flaky tests detected in ad73248. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/25483374110
|
andrewserong
left a comment
There was a problem hiding this comment.
Just left a few questions, but thanks again for taking a pass at this. Aside from the ESCAPE key thingie, it's looking pretty good to me so far!
Thanks for the feedback - you're right! I went down a rabbit hole. I'll pare this PR back. Voice Over is very finicky so it's probably better to target those sort of changes in another PR if they become a problem. |
…d focus management - Removed unnecessary crop area references and streamlined focus handling in the Cropper component. - Enhanced keyboard navigation by implementing an `onEscape` callback in the RectangleStencil, allowing users to return focus to the crop area. - Updated tests to reflect changes in focus behavior and ensure proper handling of Escape key events. These modifications aim to enhance the user experience for keyboard users and improve overall accessibility in the media editor.
- Modified the comment for the `onEscape` callback in the `StencilProps` interface to clarify that it is triggered when Escape is pressed on a resize handle, enhancing code readability and understanding. This change aims to improve documentation clarity for developers working with the media editor components.
…management - Renamed the `handleStencilEscape` function to `handleEscape` for clarity and updated its implementation to enhance focus management when the Escape key is pressed during resizing. - Revised comments in the `RectangleStencil` component to better describe keyboard interactions, specifically regarding the Escape key and arrow key functionality. These changes aim to improve code readability and enhance the user experience for keyboard navigation in the media editor.
|
I've pared this PR right back. No more structural changes or weird comment updates 😄 Voice Over stuff should be its own PR. So this PR is mainly fixing focus and updating a few announcements |
|
Size Change: +374 B (0%) Total Size: 7.95 MB 📦 View Changed
ℹ️ View Unchanged
|
andrewserong
left a comment
There was a problem hiding this comment.
Overall looking good! We don't need to address everything in this PR, but a couple of things I noticed while using VoiceOver:
- When I move the drag handles by keyboard it starts to tell me when I've made some changes, but after the first announcement, if I make subsequent moves, it doesn't seem to always announce again so it's hard to know if I've made a change.
- The crop area when focused with VoiceOver open isn't the same visually as the actual crop area (I.e. the area focused is larger than the highlighted crop area, I wonder if there's a simple way to make them the same)
- When I drag the drag handles, the VoiceOver outline sometimes drifts from the position of the drag handle
In any case, this is all an improvement over trunk, so looks good to land to me, and we can keep iterating 👍
Code-wise, looks like Copilot found a useLayoutEffect dependency that needs updating? Otherwise LGTM
|
Yeah Voice Over has its own needs I've discovered 🤣 Thanks for testing! |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Description
Improves keyboard and screen reader behavior in the experimental media editor crop flow.
The changes avoid VoiceOver-specific structural work for now. That can be handled separately if we decide to change the cropper DOM/focus structure.
Manual testing
aria-haspopup="dialog"only when the media editor modal flow is active.