MDL-79157 output: fix menu subpanels keyboard navigation

This commit is contained in:
Ferran Recio 2023-09-28 18:22:08 +02:00
parent 1724362afc
commit 0c6a581f1e
4 changed files with 75 additions and 14 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -27,10 +27,15 @@ import {
isBehatSite,
isExtraSmall,
firstFocusableElement,
lastFocusableElement,
previousFocusableElement,
nextFocusableElement,
} from 'core/pagehelpers';
import Pending from 'core/pending';
import {
hide,
unhide,
} from 'core/aria';
const Selectors = {
mainMenu: '[role="menu"]',
@ -104,6 +109,15 @@ class SubPanel {
this.element = element;
this.menuItem = element.querySelector(Selectors.subPanelMenuItem);
this.panelContent = element.querySelector(Selectors.subPanelContent);
/**
* Enable preview when the menu item has focus.
*
* This is disabled when the user press ESC or shift+TAB to force closing
*
* @type {Boolean}
* @private
*/
this.showPreviewOnFocus = true;
}
/**
@ -171,7 +185,10 @@ class SubPanel {
* Main element focus in handler.
*/
_mainElementFocusInHandler() {
if (this._needSmallSpaceBehaviour()) {
if (this._needSmallSpaceBehaviour() || !this.showPreviewOnFocus) {
// Preview is disabled when the user press ESC or shift+TAB to force closing
// but if the continue navigating with keyboard the preview is enabled again.
this.showPreviewOnFocus = true;
return;
}
this.setVisibility(true);
@ -228,10 +245,10 @@ class SubPanel {
// Keys to move focus to the panel.
let focusPanel = false;
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft' || (event.key === 'Tab' && !event.shiftKey)) {
focusPanel = true;
}
if ((event.key === 'Enter' || event.key === ' ') && !this._needSmallSpaceBehaviour()) {
if ((event.key === 'Enter' || event.key === ' ')) {
focusPanel = true;
}
// In extra small screen the panel is shown below the item.
@ -261,6 +278,13 @@ class SubPanel {
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
newFocus = this.menuItem;
}
// Acording to WCAG Esc and Tab are similar to arrow navigation but they
// force the subpanel to be closed.
if (event.key === 'Escape' || (event.key === 'Tab' && event.shiftKey)) {
newFocus = this.menuItem;
this.setVisibility(false);
this.showPreviewOnFocus = false;
}
if (event.key === 'ArrowUp') {
newFocus = previousFocusableElement(this.panelContent, canLoop);
isBrowsingSubPanel = true;
@ -269,6 +293,14 @@ class SubPanel {
newFocus = nextFocusableElement(this.panelContent, canLoop);
isBrowsingSubPanel = true;
}
if (event.key === 'Home') {
newFocus = firstFocusableElement(this.panelContent);
isBrowsingSubPanel = true;
}
if (event.key === 'End') {
newFocus = lastFocusableElement(this.panelContent);
isBrowsingSubPanel = true;
}
// If the user cannot loop and arrive to the start/end of the subpanel
// we focus on the menu item.
if (newFocus === null && isBrowsingSubPanel && !canLoop) {
@ -306,6 +338,13 @@ class SubPanel {
if (visible) {
this._hideOtherSubPanels();
}
// Aria hidden/unhidden can alter the focus, we only want to do it when needed.
if (!visible && this.getVisibility) {
hide(this.panelContent);
}
if (visible && !this.getVisibility) {
unhide(this.panelContent);
}
this.menuItem.setAttribute('aria-expanded', visible ? 'true' : 'false');
this.panelContent.classList.toggle('show', visible);
this.element.classList.toggle(Classes.contentDisplayed, visible);

View File

@ -139,10 +139,9 @@ Feature: Navigate action menu subpanels
And I should not see "Status B" in the "regularscenario" "region"
And I should see "Status C" in the "regularscenario" "region"
And I should see "Status D" in the "regularscenario" "region"
And the focused element is "Status C" "link" in the "regularscenario" "region"
# Loop the subpanel links wand the menu item with up and down.
Then I press the down key
And the focused element is "Status C" "link" in the "regularscenario" "region"
And I press the down key
And the focused element is "Status D" "link" in the "regularscenario" "region"
And I press the down key
And the focused element is "Another subpanel" "menuitem" in the "regularscenario" "region"
@ -164,9 +163,9 @@ Feature: Navigate action menu subpanels
# Enter the panel and select the second link.
And I press the enter key
And I press the down key
And the focused element is "Status A" "link" in the "regularscenario" "region"
And the focused element is "Status B" "link" in the "regularscenario" "region"
And I press the enter key
And I should see "Foo param value: Aardvark" in the "paramcheck" "region"
And I should see "Foo param value: Beetle" in the "paramcheck" "region"
Scenario: action menu subpanels can display optional icons in the menu item
Given I click on "Actions menu" "button" in the "regularscenario" "region"
@ -196,10 +195,9 @@ Feature: Navigate action menu subpanels
And I should not see "Status B" in the "drawersimulation" "region"
And I should see "Status C" in the "drawersimulation" "region"
And I should see "Status D" in the "drawersimulation" "region"
And the focused element is "Status C" "link" in the "drawersimulation" "region"
# Loop the subpanel links wand the menu item with up and down.
Then I press the down key
And the focused element is "Status C" "link" in the "drawersimulation" "region"
And I press the down key
And the focused element is "Status D" "link" in the "drawersimulation" "region"
And I press the down key
And the focused element is "Another subpanel" "menuitem" in the "drawersimulation" "region"
@ -222,6 +220,30 @@ Feature: Navigate action menu subpanels
# Enter the panel and select the second link.
And I press the enter key
And I press the down key
And the focused element is "Status A" "link" in the "drawersimulation" "region"
And the focused element is "Status B" "link" in the "drawersimulation" "region"
And I press the enter key
And I should see "Foo param value: Aardvark" in the "paramcheck" "region"
And I should see "Foo param value: Beetle" in the "paramcheck" "region"
Scenario: User can browse the menu using the WCAG recommended compount keyboard navigation
Given I click on "Actions menu" "button" in the "regularscenario" "region"
And I press the down key
And I press the down key
And I press the down key
And the focused element is "Subpanel example" "menuitem" in the "regularscenario" "region"
When I press the tab key
And the focused element is "Status A" "link" in the "regularscenario" "region"
And I should see "Status A" in the "regularscenario" "region"
And I should see "Status B" in the "regularscenario" "region"
And I press the down key
Then I press the shift tab key
And the focused element is "Subpanel example" "menuitem" in the "regularscenario" "region"
And I should not see "Status A" in the "regularscenario" "region"
And I should not see "Status B" in the "regularscenario" "region"
And I press the enter key
And the focused element is "Status A" "link" in the "regularscenario" "region"
And I should see "Status A" in the "regularscenario" "region"
And I should see "Status B" in the "regularscenario" "region"
And I press the escape key
And the focused element is "Subpanel example" "menuitem" in the "regularscenario" "region"
And I should not see "Status A" in the "regularscenario" "region"
And I should not see "Status B" in the "regularscenario" "region"