-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Navigation block: Do not toggle aria-expanded on hover when the overlay menu is opened #52170
Navigation block: Do not toggle aria-expanded on hover when the overlay menu is opened #52170
Conversation
@@ -103,7 +103,7 @@ function block_core_navigation_add_directives_to_submenu( $w, $block_attributes | |||
) ) { | |||
// Add directives to the parent `<li>`. | |||
$w->set_attribute( 'data-wp-interactive', true ); | |||
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": false } } }' ); | |||
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "submenuOpenedBy": {}, "type": "submenu" } } }' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest version of deepsignal
includes an ownKey
trap, so we don't need to initialize "click"
and "hover"
anymore.
'<button aria-haspopup="true" %3$s class="%6$s" data-micromodal-trigger="%1$s" %11$s>%9$s</button> | ||
'<button aria-haspopup="true" %3$s class="%6$s" %11$s>%9$s</button> | ||
<div class="%5$s" style="%7$s" id="%1$s" %12$s> | ||
<div class="wp-block-navigation__responsive-close" tabindex="-1" data-micromodal-close> | ||
<div class="wp-block-navigation__responsive-close" tabindex="-1"> | ||
<div class="wp-block-navigation__responsive-dialog" aria-label="%8$s" %13$s> | ||
<button %4$s data-micromodal-close class="wp-block-navigation__responsive-container-close" %14$s>%10$s</button> | ||
<button %4$s class="wp-block-navigation__responsive-container-close" %14$s>%10$s</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed some micromodal
leftovers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those attributes were added back in this pull request because in WordPress 6.3, without Gutenberg installed, we decided to keep the old implementation, which needs them. I assume that, as we intend to include it in the next release 🤞 , should we revert the whole pull request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, we're pass the 6.3 feature freeze, so feel free to remove anything from the old implementation that is not needed anymore.
closeMenuOnHover( args ) { | ||
closeMenu( args, 'hover' ); | ||
closeMenuOnHover( store ) { | ||
closeMenu( store, 'hover' ); | ||
}, | ||
openMenuOnClick( args ) { | ||
openMenu( args, 'click' ); | ||
openMenuOnClick( store ) { | ||
openMenu( store, 'click' ); | ||
}, | ||
closeMenuOnClick( args ) { | ||
closeMenu( args, 'click' ); | ||
closeMenuOnClick( store ) { | ||
closeMenu( store, 'click' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed args
to store
everywhere because it feels more natural.
store( { | ||
wpStore( { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed this to wpStore
to be able to use store
instead of args
in the functions.
// Check if the menu is still open or not. | ||
if ( ! selectors.core.navigation.isMenuOpen( { context } ) ) { | ||
if ( ! selectors.core.navigation.isMenuOpen( store ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started passing store
instead of {context}
to the selector. I think it's safer to do it that way by default.
if ( | ||
context.core.navigation.overlay && | ||
( event.key === 'Tab' || event.keyCode === 9 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the keyCode
s because they are deprecated and not needed in modern browsers: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
'area[href]', | ||
'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', | ||
'select:not([disabled]):not([aria-hidden])', | ||
'textarea:not([disabled]):not([aria-hidden])', | ||
'button:not([disabled]):not([aria-hidden])', | ||
'iframe', | ||
'object', | ||
'embed', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the elements that are unnecessary for the menu. If in the future we need them, we can add them back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember correctly, we added all the focusable elements in case other blocks, like the image block, copy and paste that logic and they need it in this case. Maybe we can abstract it somehow (in the interactivity
package?) if we see this is a common use case?
Anyway, right now it makes sense to keep only the necessary ones 👍
// Only open on hover if the overlay is closed. | ||
Object.values( | ||
navigation.overlayOpenedBy || {} | ||
).filter( Boolean ).length === 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the main change of this PR, where we check if the parent overlay is opened or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be safe to include a global variable to check if the overlay is opened? I can imagine other use cases where it could be handy to check store.state.core.navigation.overlayMenuOpened
, or something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but I would only add it when there's a real need for it 🙂
Size Change: +187 B (0%) Total Size: 1.42 MB
ℹ️ View Unchanged
|
Flaky tests detected in 3f0530a. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5422620048
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested and it seems to be working as you describe 🙂 Apart from some minor comments I left, I have one question:
What should be the value of aria-expanded
when the overlay menu is opened? Right now, it is false, but maybe it shouldn't exist at all? I don't know that much about accessibility but, if the submenu is always opened, it seems weird to me to have an aria-expanded="false"
attribute (although I believe it is how it works with the previous implementation).
? 'dialog' | ||
: '', | ||
: ''; | ||
}, | ||
isMenuOpen: ( { context } ) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use store
here for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I'm using store
only when the function is using at least one selector 🙂
: 'submenuOpenedBy' | ||
] | ||
).filter( Boolean ).length > 0, | ||
menuOpenBy: ( { context } ) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: Shouldn't we use store
here for consistency?
I don't know, maybe. But I think we can merge this PR, and if it turns out that it's better to remove it, do it in another PR. |
Thanks, Mario! I'm going to merge this now 🙂 |
What?
Do not toggle
aria-expanded
on hover of the submenus when the overlay menu is opened.Why?
Because the submenus are expanded by defualt when the overlay menu is opened.
How?
I divided
isMenuOpen
into two different properties (overlayOpenedBy
andsubmenuOpenedBy
) so it's possible to know if the parent overlay is opened or not in the children submenu. I also changed theoverlay
boolean totype = "overlay"
ortype = "submenu"
to make it more explicit.I also updated
deepsignal
and removed the leftovers in theblock-library
'spackage.json
.Testing Instructions
aria-expanded
attribute of the submenus turnstrue
on hoveraria-expanded
attribute of the submenus doesn't turntrue
on hoverScreenshots or screencast
Before
Screen.Capture.on.2023-06-30.at.13-51-49.mp4
After
Screen.Capture.on.2023-06-30.at.13-49-01.mp4