-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fixes focus issue for contextual menus #4744
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
Fixes focus issue for contextual menus #4744
Conversation
| onMenuClick(ev, this); | ||
| } | ||
|
|
||
| const menuProps = this.props.menuProps; |
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.
Should do:
const menuProps = {
...this.props.menuProps,
shouldFocusOnContainer: true
};Avoid modifying existing props objects.
|
|
||
| if (!ev.defaultPrevented) { | ||
| const menuProps = this.props.menuProps; | ||
| if (menuProps) { |
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 comment regarding using ... to mix in a new prop.
| > | ||
| <div | ||
| role='menu' | ||
| role={ shouldFocusOnContainer ? 'menu' : undefined } |
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.
Why should the role change based on whether or not it is focusable? What gets labeled as a menu in the other case?
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.
So when focus is NOT on the container (and is instead on the first menu item), adding role='menu' to the container stopped Narrator from reading the aria-label on the menu. Role='group' was fine but so was no role at all for narration behavior. Currently nothing gets labeled as a menu in the case where focus is on the first menu item (and narration works optimally). Is it a big accessibility no-no to not have role='menu' somewhere on a menu?
|
This works great. Tested in Narrator on Edge and with a mouse. |
chang47
left a comment
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.
Adding some comments
| handleTabKey={ FocusZoneTabbableElements.all } | ||
| > | ||
| <ul | ||
| role='presentation' |
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.
Why are we getting rid of the role?
At the very least shouldn't it be something like:
role = { shouldFocusOnContainer ? 'presentation' : undefined }
to match with your changes above.
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 role='presentation' was useless and it's presence didn't impact screen reader behavior at all.
| id={ id } | ||
| className={ this._classNames.container } | ||
| tabIndex={ 0 } | ||
| tabIndex={ shouldFocusOnContainer ? 0 : undefined } |
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.
For my understanding, this is the part of the code where we prevent focus being added to the container for the contextual menu?
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.
Yes.
| this._onSubMenuDismiss(ev); | ||
| } else { // This has a collapsed sub menu. Expand it. | ||
| this.setState({ | ||
| expandedByMouseClick: (ev.nativeEvent.detail !== 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.
Since we added a comment in BaseButton regarding why we're using:
ev.nativeEvent.detail
Let's put it here too.
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.
Good idea!
scripts/package.json
Outdated
| "bundlesize": [ | ||
| { | ||
| "path": "../apps/test-bundle-button/dist/test-bundle-button.min.js", | ||
| "maxSize": "47.6 kB" |
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.
Worth noting that the current size in the most up to date version of master is 49.6 so this is not a bump of 2KB
* master: (52 commits) Marqueeselection style update (microsoft#4803) Applying package updates. FocusZone: Add the ability to stop focus from propagating outside the FocusZone (microsoft#4823) Unknown persona coin (microsoft#4809) Applying package updates. BaseButton: Allow Alt + Down on menu buttons to open the menu (microsoft#4807) Applying package updates. Website: Scroll to top of page on navigation (microsoft#4810) Applying package updates. ActivityItem: fix getstyles (microsoft#4802) Mark Slider#ValuePosition enum as deprecated as it is unused. (microsoft#4799) Icon: ensure `styles` still works. (microsoft#4805) Popup: Added check for onBlur to prevent focus setting focus to be incorrectly disabled when closing a menu in Chrome (microsoft#4804) Update package.json Move <Layer> to use React portals when available (microsoft#4724) Fix breadcrumb rendering issue when overflow item is at last index (microsoft#4787) Fixes focus issue for contextual menus (microsoft#4744) Remove redundant selected items prop on BaseExtendedPicker (microsoft#4769) SearchBox: New prop for turning off icon animation (microsoft#4794) Add functions to ContextualMenuItem to open and close menus on command (microsoft#4741) ...
Pull request checklist
$ npm run changeDescription of changes
Prior to fix, when a contextual menu was opened, focus always went to the contextual menu container.
The correct behavior (determined via discussion with Jeremy Spurlin/ Ben Truelove/ Chris Schlechty/ Jon Schectman/ Thomas Michon) is as follows:
If user activates contextual menu via keyboarding (pressing enter on a button for example), focus should go to the first focusable menu item.
If user activates contextual menu via mouse click, focus should go to the contextual menu container.
The following is a summary of changes to each file:
BaseButton.tsx: Pipes through to ContextualMenu via new param (shouldFocusOnContainer) how the menu was opened. Right now we disregard user input for "shouldFocusOnContainer" if contextual menu is created via menu params to button. I think that is actually desired behavior as it means we will enforce accessibility. Tweaked _isValidMenuOpenKey so that way "Enter" is considered the valid menu open key for non split button items. This means that on enter key press, _onMenuKeyDown will be executed instead of _onMenuClick.
ContextualMenu.tsx: Responds to new param shouldFocusOnContainer, setting roles and tab indexes appropriately. Note that aria label is read regardless of if focus is put on container or first menu item. Added state expandedByMouseClick so that way the same focus behavior applies to sub-menus.
Focus areas to test
With Narrator on and off (in Edge), test contextual menus, activating via keyboard or via click. Observe different focus behaviors.