-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Partially port #5385 & #9003 to improve Dropdown accessibility in office-ui-fabric-react/5.79.1 #18075
Partially port #5385 & #9003 to improve Dropdown accessibility in office-ui-fabric-react/5.79.1 #18075
Conversation
Update Office UI fabric react v5.79.1
Would appreciate if @smhigley or someone else from @microsoft/fluentui-react-pickers-and-more could help review this, keeping in mind that this is a hotfix to a VERY old version and so changes need to be more minimal. |
…i-fabric-react/5.79.1
@ecraig12345 could you please help to assign this PR to the specific expertise? It seems this team's hovercard is not available. Thank you so much |
…i-fabric-react/5.79.1
@ecraig12345 Could you please help to assign this PR to more expertise? Since our SharePoint OnPrem team is going to release new SharePoint Public Preview at the end of May, it is urgent for us to merge this PR to resolve some critical Accessibility bugs. |
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.
Thanks for the PR! I have some requests around role structure and attributes to have it better reflect the combobox pattern with the best support now.
This pattern is a good ref: https://w3c.github.io/aria-practices/examples/combobox/combobox-select-only.html. It shows a single-select combo, but could be updated to a multiselect by adding aria-multiselectable="true"
to the root.
|
||
if (!isOpen && selectedIndices.length === 0 && !multiSelect && !disabled) { | ||
// Per aria | ||
this._moveIndex(1, 0, -1); |
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 changes the value of the dropdown on focus, which we'd want to avoid. It looks like the only thing this function should do is update the hasFocus
state
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.
@smhigley Thanks, will remove it.
aria-readonly='true' | ||
role={ ariaAttrs.childRole } | ||
aria-live={ !hasFocus || disabled || multiSelect || isOpen ? 'off' : 'assertive' } | ||
aria-label={ selectedOptions.length ? selectedOptions[0].text : this.props.placeHolder } |
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'd suggest not adding an aria-label
at all. It'll have an inconsistent effect on the live region (technically the live region should read the text content and not the aria-label, but it varies in practice), and I can't think of a reason a screen reader user should get different information about the current value than a sighted user.
Additionally, elements without nameable roles (e.g. <div>
s and <span>
s) don't support aria-label
or aria-labelledby
.
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 I add 'textbox' role in span
, I also add 'title' in span
in order to avoid errors from Accessibility Insights.
@@ -191,8 +206,9 @@ export class Dropdown extends BaseComponent<IDropdownInternalProps, IDropdownSta | |||
(errorMessage && errorMessage.length > 0 ? styles.titleIsError : null)) | |||
} | |||
aria-atomic={ true } | |||
role='listbox' | |||
aria-readonly='true' | |||
role={ ariaAttrs.childRole } |
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.
While the role of this definitely shouldn't be listbox
, it also can't be option
once the parent is updated back to combobox
. This element actually doesn't need any role -- it can just be a text node and live region, and that's enough to provide the parent combobox with a value.
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.
Will keep 'combobox'
@@ -160,27 +175,27 @@ export class Dropdown extends BaseComponent<IDropdownInternalProps, IDropdownSta | |||
id={ id } | |||
tabIndex={ disabled ? -1 : 0 } | |||
aria-expanded={ isOpen ? 'true' : 'false' } | |||
role='combobox' |
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 element would actually need to stay a combobox -- it should be a combo whether it's single or multiselect, the only difference is we should add aria-multiselectable="true/false"
.
The issue with having a single-select be a listbox is that listboxes do not have an expand/collapse functionality, and would set up a screen reader user's expectations that it behave like a listbox. The issue with not having a role at all is then we have a focusable generic element that still has a name/description and provides no information on how to interact with it.
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.
@smhigley Thanks for your comments. I have a question here: If I use role='combobox', but Accessibility Insights will scan a bug: Required ARIA child role not present: textbox. So how about I add role="textbox' in <span?
And this error also occurs in https://w3c.github.io/aria-practices/examples/combobox/combobox-select-only.html and https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown
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.
Ah, I should've mentioned that off the bat 😅. Including the textbox
role as a child of a combobox is the ARIA 1.1 pattern, and actually has significantly worse screen reader support in practice than leaving it off (and if included, it would need to be the element that gets focus). Having the combobox
be the single interactive element is the ARIA 1.2 pattern, which has good screen reader support across the board.
Unfortunately, axe-core has yet to update its rules for combobox, so it still flags it as an error 😭. The issue open against them is here: dequelabs/axe-core#2505
For now, it'd still be better to go with the pattern with good support (no textbox), and ignore/skip the automated error until they fix it.
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.
Thank you @smhigley for letting me know about this. It is really a good chance for me to learn more about ARIA pattern and axe-core. Really appreciate your support.
aria-label={ ariaLabel } | ||
aria-describedby={ id + '-option' } | ||
aria-activedescendant={ isOpen && selectedIndices.length === 1 && selectedIndices[0] >= 0 ? (this._id + '-list' + selectedIndices[0]) : null } | ||
aria-labelledby={ id + '-label' } |
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.
❤
…hub.com/Phoebe-0319/fluentui into hotfix_15/office-ui-fabric-react/5.79.1
className={ css( | ||
'ms-Dropdown-title', styles.title, | ||
!selectedOptions.length && 'ms-Dropdown-titleIsPlaceHolder', | ||
!selectedOptions.length && styles.titleIsPlaceHolder, | ||
(errorMessage && errorMessage.length > 0 ? styles.titleIsError : null)) | ||
} | ||
aria-atomic={ true } | ||
role='listbox' | ||
aria-readonly='true' | ||
aria-live='off' |
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 aria-live
fix you had here earlier actually looked quite good to me (unless you removed it for some other comment that I missed) 😅. While often aria-live is misused, in this case the logic you used for it locked it down well, and I think it should give some benefit for screen reader users changing the value with the combo collapsed
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.
Will keep the previous design.
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.
🎉
….79.1 to hotfix/5.135.6
Pull request checklist
$ rush change
Description of changes
Partially port #5385 & #9003 to improve Dropdown accessibility in office-ui-fabric-react/5.79.1
Focus areas to test
(optional)