Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components: Split MenuItem label and description for accessibility #69372

Open
wants to merge 3 commits into
base: trunk
Choose a base branch
from

Conversation

im3dabasia
Copy link
Contributor

What?

Closes #58720

This PR updates the MenuItem component to properly separate its accessible name (children text) and accessible description (info text). Previously, both children and info were combined into the accessible name, leading to overly long and unclear labels for assistive technology users.

Why?

The info text was incorrectly included in the accessible name, causing issues such as:

  • Overly long and confusing labels, making screen readers harder to use.
  • Difficulties with voice activation, as users had to speak the full label, including the extra info.

How?

  • Keeps children as the accessible name and references info via aria-describedby for a separate description.
  • Uses aria-hidden="true" to prevent redundancy while preserving the visual design.

Testing Instructions for Keyboard

  1. Add a new post in the editor.
  2. Insert an image block.
  3. Click on the link or alignment options.
  4. Using the Tab key, navigate down to a menu item that has both a dark label (the title) and a lighter label (the description).
  5. Verify that the screen reader now correctly treats the dark label as the accessible name and the lighter label as the description.
  6. Ensure that navigating with Tab and Arrow keys moves focus correctly between menu items.
  7. Confirm that the name includes only the children, and the description (info) is announced separately.

Screenshots

Before After
Screenshot 2025-02-28 at 10 37 46 PM Screenshot 2025-02-28 at 10 45 38 PM

|

Before After
Screenshot 2025-02-28 at 10 41 07 PM Screenshot 2025-02-28 at 10 35 56 PM

Copy link

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org>
Co-authored-by: afercia <afercia@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@shail-mehta shail-mehta added [Type] Bug An existing feature does not function as intended [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Package] Components /packages/components labels Mar 1, 2025
@im3dabasia
Copy link
Contributor Author

Hey @afercia

When you have a moment, could you please review my PR and share your thoughts on it?

Thank you

if ( info ) {
const labelId = `menu-item-label-${ uuidv4() }`;
const descriptionId = `menu-item-description-${ uuidv4() }`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To generate unique IDs Gutenberg provides the useInstanceId hook. See a simple example here, where you can pass 1) the component's name. 2) a string that will be used as prefix to the increasing number generated by useInstanceId.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second to this, I understand that using uuid's would cause performance issues and would soon update the code to use instanceId

</span>
<span id={ descriptionId } className="screen-reader-text">
{ info }
</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move the info span outside of the children markup entirely and use a hidden html attribute instead of className="screen-reader-text". It can eveb be placed outside of the Item. This way the markup would be cleaner and there wouldn't be the need to use labelId and aria-labelledby because the labeling would simply use the content.

Copy link
Contributor

@afercia afercia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments, please have a look.

The approach is good to me and it is similar to what I'm proposing for the Post Summary controls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Package] Components /packages/components [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MenuItem: split content and info prop into accessible name and accessible description
3 participants