Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ describe( 'NavigationMenuSelector', () => {
screen.queryByRole( 'menuitem', {
name: 'Create new Menu',
} )
).toBeDisabled();
).toHaveAttribute( 'aria-disabled', 'true' );

// once the menu is created
// no more network activity to wait on
Expand Down Expand Up @@ -619,7 +619,7 @@ describe( 'NavigationMenuSelector', () => {
// Check all menu items are present but disabled.
screen.getAllByRole( 'menuitem' ).forEach( ( item ) => {
// // Check all menu items are present but disabled.
expect( item ).toBeDisabled();
expect( item ).toHaveAttribute( 'aria-disabled', 'true' );
} );

// once the menu is imported
Expand Down
4 changes: 4 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Bug fixes

- `MenuItem`: make accessible when disabled ([#71251](https://github.com/WordPress/gutenberg/pull/71251)).

### Enhancement

- Upgrade `gradient-parser` to version `1.1.1` to support HSL/HSLA color, CSS variables, and `calc()` expressions ([#71186](https://github.com/WordPress/gutenberg/pull/71186)).
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/menu-item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function UnforwardedMenuItem(
role={ role }
icon={ iconPosition === 'left' ? icon : undefined }
className={ className }
accessibleWhenDisabled
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interestingly, the bug fixed by this PR doesn't occur when using DropdownMenu's controls prop (as opposed to using the children prop).

That is because DropdownMenu internally doesn't use MenuItem when mapping over the controls prop, but uses the Button component directly and sets the accessibleWhenDisabled prop already:

accessibleWhenDisabled
disabled={ control.isDisabled }
>
{ control.title }
</Button>

I would typically work on refactoring DropdownMenu to use MenuItem internally, but it's probably not worth it given that we already have a newer Menu component, and the upcoming DS effort

Copy link
Member

Choose a reason for hiding this comment

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

Is accessibleWhenDisabled something that we want to keep optional for MenuItem?

Copy link
Contributor Author

@ciampo ciampo Aug 19, 2025

Choose a reason for hiding this comment

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

I don't think so — since MenuItem is supposed to be part of a Menu (and therefore, a composite widget), it makes sense for it to be always accessible when disabled (ie. focusable + aria-disabled attribute + no-op on click events).

Moreover, this change aligns with other menu impementations:

  • the DropdownMenu component already sets accessibleWhenDisabled internally when using the controls prop instead of children (see this comment);
  • other established component libraries, such as Ariakit and Base UI, also apply the same treatment (ie. focusable + aria-disabled attribute + no-op on click events) to their disabled menu items;
  • inherently, the new (experimental) Menu component also behaves the same way

In short, I don't think consumers should (or would) set a menu item as non-accessible while disabled.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for confirming 👍

{ ...buttonProps }
>
<span className="components-menu-item__item">{ children }</span>
Expand Down
Loading