Gutenberg: Investigate creating an accessible custom select/dropdown component

Created on 9 Jul 2019  Β·  57Comments  Β·  Source: WordPress/gutenberg

Is your feature request related to a problem? Please describe.

HTML select elements are not visually customisable, and in some circumstances we need to customise the options in a dropdown. When showing available text styles, for example:

Screen Shot 2019-07-09 at 2 09 38 pm

We also need these dropdowns to be fully accessible when used with keyboard, screen readers, voice commands, and any assistive technology.

Describe the solution you'd like

Investigate how to best achieve full accessibility while using non-semantic markup, with ARIA and custom keyboard interaction.
Previous discussion for reference:
https://github.com/WordPress/gutenberg/pull/16148

Deque's custom select might be a good solution: https://pattern-library.dequelabs.com/components/selects

React-select is another possibility; there's ongoing work/discussion on accessibility improvements over there: https://github.com/JedWatson/react-select/issues/2456

Accessibility (a11y) Needs Accessibility Feedback [Status] In Progress [a11y] Epic

Most helpful comment

I'd like to post some testing results, split in comments for each main topic. Before that, please allow me to make some preliminary, important, remarks.

As discussed on Slack, the prevalent opinion in the Accessibility team is to recommend to use a native <select> element. For the many reasons explained on the Slack discussion and on the WPCampus report.

Aslo, as mentioned in a previous comment, some W3C folks are considering to standardise form controls and components to be able (amongst other things) to fully style native <select> elements.

The proposal is included in the Web Incubator Community Group (WICG) and it's in an investigation phase. Ongoing discussion is taking place on the WICG Discourse.

Worth noting that on Windows modern browsers the <select> options can already be styled, to some extent:

select options styled

(selects style-ability exploration by Mason Freed)

Personally, I do believe WordPress is today in a position to participate in the W3C discussion and positively influence the process. I'd like to suggest to the project leads to take into consideration this option, as it seems the best way to improve the web for everyone (a little step at a time).

That said, the Accessibility team aims for a constructive spirit of collaboration across teams and is willing to explore and test all the available options as much as it can.

All 57 comments

cc. @epiqueras who I think was looking into this a little.

It's @enriquesanchez πŸ˜†

I tested both Deque's custom select and React-select on Mac (Safari + VoiceOver) and Windows (Firefox + NVDA).

Deque's custom select worked like charm in both cases. React-select did not work well for me, I had trouble getting the screen reader to properly read aloud the available options.

My vote goes for moving forward with Deque's custom select, I think it would allow us to have custom styling on dropdowns (for font selection, text size, etc.) like we used to while also being accessible.

57712309-03e57300-7679-11e9-95a2-e9f36eb31ba2

I'm adding the 'Needs Accessibility Feedback' label in order to get more eyes from the a11y team and see what they think.

The discussions in #16666, are relevant here.

...a single input component when there are other lightweight alternatives that could power the accessibility foundations of any input type.

I would start by looking at https://ui.reach.tech or https://github.com/downshift-js/downshift if we need a lower level API.

The discussions in #16666, are relevant here.

On #16666 what's being discussed is an "autocompleter", which is a bit different from a select replacement. I've commented there, see https://github.com/WordPress/gutenberg/pull/16666#issuecomment-518795243

in some circumstances we need to customise the options in a dropdown

Assuming Gutenberg really needs a <select> replacement:

In the last 5 years the accessibility team tested various select-replacement libraries. Most of them are not accessible:

Here's the Select2 accessibility testing and evaluation the a11y team posted on September 2015: https://make.wordpress.org/accessibility/2015/09/07/accessibility-usertest-select2/

See also
https://github.com/WordPress/gutenberg/pull/5921#issuecomment-391652557
(24 May 2018)

Since then, some new select replacement like SelectWoo and react-select improved some of the accessibility issues but they're still not fully accessible.

https://github.com/WordPress/gutenberg/pull/5921#issuecomment-377903088
(2 Apr 2018)

From an accessibility perspective, react-select is not so different from Select2. Unfortunately, it is not accessible.

Both Select2 and react-select have accessibility-related open issues and some work is (slowly) being done. As of today, they're still not accessible.

The Deque custom select looks promising and maybe it would be a nice opportunity to collaborate with Deque to refine some details.

Finally, looks like some W3C folks are considering to standardise and make fully styleable the native <select> element and other form controls: https://twitter.com/gregwhitworth/status/1150771325075542016

The proposal is included in the Web Incubator Community Group (WICG) and it's in an investigation phase. [Edit] This link is dead, please refer to https://github.com/WICG/open-ui and https://open-ui.org/

Accesible autocompleters/comboboxes and dropdowns/selects usually share a
lot of code.

That’s why I proposed 2 of the most popular libraries for easily
implementing accessible inputs to power all of them.

On Tue, Aug 6, 2019 at 7:13 PM Andrea Fercia notifications@github.com
wrote:

The discussions in #16666
https://github.com/WordPress/gutenberg/pull/16666, are relevant here.

On #16666 https://github.com/WordPress/gutenberg/pull/16666 what's
being discussed is an "autocompleter", which is a bit different from a
select replacement. I've commented there, see #16666 (comment)
https://github.com/WordPress/gutenberg/pull/16666#issuecomment-518795243

in some circumstances we need to customise the options in a dropdown

Assuming Gutenberg really needs a element and other form controls:
https://twitter.com/gregwhitworth/status/1150771325075542016

The proposal is included in the Web Incubator Community Group (WICG)
https://github.com/WICG and it's in an investigation phase
https://github.com/WICG/form-controls-components/blob/master/select/overview.md
.

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/WordPress/gutenberg/issues/16473?email_source=notifications&email_token=AESFA2CWZJTPYFLXLSP7PHTQDIARJA5CNFSM4H7BNANKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3WXAOI#issuecomment-518877241,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AESFA2DPLPJFBO4I2JOPOBTQDIARJANCNFSM4H7BNANA
.

Accesible autocompleters/comboboxes and dropdowns/selects usually share a lot of code.

Selects and autocompletes may look a bit similar, but their purpose is quite different: select presents you with a limited list of choices from which you can select one or more options; autocomplete is essentially a search type input with a bit of added functionality. Here's a really good talk about what it takes to build an accessible autocomplete: https://www.youtube.com/watch?v=_w6KvvN9cWw (spoiler: it's anything but easy πŸ˜„)

My take on this is that it's better to have two solid single-purpose components than one bloated one that tries to do everything at once. There may be utility functions, e.g. for keyboard navigation, that we can share between components, but they shouldn't have much more in common than that.

Comboboxes are dropdowns with dynamic options derived from a text input.

Take a look at the code for the libraries I suggested, Reach and Downshift.

On Tue, Aug 6, 2019 at 8:45 PM tellthemachines notifications@github.com
wrote:

Accesible autocompleters/comboboxes and dropdowns/selects usually share a
lot of code.

Selects and autocompletes may look a bit similar, but their purpose is
quite different: select presents you with a limited list of choices from
which you can select one or more options; autocomplete is essentially a
search type input with a bit of added functionality. Here's a really good
talk about what it takes to build an accessible autocomplete:
https://www.youtube.com/watch?v=_w6KvvN9cWw (spoiler: it's anything but
easy πŸ˜„)

My take on this is that it's better to have two solid single-purpose
components than one bloated one that tries to do everything at once. There
may be utility functions, e.g. for keyboard navigation, that we can share
between components, but they shouldn't have much more in common than that.

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/WordPress/gutenberg/issues/16473?email_source=notifications&email_token=AESFA2H5OQ6MIHUMHLCINVDQDILJ5A5CNFSM4H7BNANKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3W3KJY#issuecomment-518894887,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AESFA2HMQBXZBZUXEAN6YT3QDILJ5ANCNFSM4H7BNANA
.

Comboboxes are dropdowns with dynamic options derived from a text input

Comboboxes are input elements where a dropdown with options is rendered based on what you type in the input. Because they are search type inputs, they need to have a reset button and a search button too.
Selects are not inputs. You can't type into them, though you can use your keyboard to pick a specific option. When you click or press space on the select, all the available options are presented in a dropdown. There's good reason for there to be a specific HTML element dedicated to them πŸ™‚

Take a look at the code for the libraries I suggested, Reach and Downshift.

Reach UI is not production ready. They don't have a select component, and their combobox example is broken: typing in any letter brings up the whole list, which is not expected behaviour. For reference, here are some examples of how comboboxes are supposed to work: https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html

According to discussion here we've already tried downshift and it wasn't accessible enough. Given that they have an open issue from Nov 2018 to look into accessibility issues, it doesn't look like they are making much progress in that area.

So how is this going to move forward? Have you tried Deque’s select which
the other Enrique recommended?

On Tue, Aug 6, 2019 at 9:35 PM tellthemachines notifications@github.com
wrote:

Comboboxes are dropdowns with dynamic options derived from a text input

Comboboxes are input elements where a dropdown with options is rendered
based on what you type in the input. Because they are search type inputs,
they need to have a reset button and a search button too.
Selects are not inputs. You can't type into them, though you can use your
keyboard to pick a specific option. When you click or press space on the
select, all the available options are presented in a dropdown. There's good
reason for there to be a specific HTML element dedicated to them πŸ™‚

Take a look at the code for the libraries I suggested, Reach and Downshift.

Reach UI is not production ready. They don't have a select component, and
their combobox example is broken: typing in any letter brings up the whole
list, which is not expected behaviour. For reference, here are some
examples of how comboboxes are supposed to work:
https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html

According to discussion here
https://github.com/WordPress/gutenberg/pull/16666#issuecomment-515459792
we've already tried downshift and it wasn't accessible enough. Given that
they have an open issue from Nov 2018
https://github.com/downshift-js/downshift/issues/617 to look into
accessibility issues, it doesn't look like they are making much progress in
that area.

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/WordPress/gutenberg/issues/16473?email_source=notifications&email_token=AESFA2D533NN2ZIBCNDO5TDQDIRFTA5CNFSM4H7BNANKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3W5Q4A#issuecomment-518903920,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AESFA2DOJ7OFWOE6PL33QDDQDIRFTANCNFSM4H7BNANA
.

Procedural note πŸ™‚Please avoid to quote the whole previous comment when replying. While the GitHub UI hides the previous comment, the notification emails show both the reply and the previous comment. Reading through all that quoted text is a terrible experience. Thank you!

I don't add it. It's the GitHub reply to email flow that does it.

Thanks for reviewing this @afercia!

collaborate with Deque to refine some details

I'm curious to know if you found any issues with Deque's implementation? I know you had some initial observations on #16148.

@enriquesanchez thank you for reviewing and for the ping on Slack!

Testing the two selects on https://pattern-library.dequelabs.com/components/selects with screen readers on Windows, here's some random observations compared to native behavior:

native <select> elements:

  • both JAWS and NVDA announce them as combo box
  • NVDA + Firefox announce the select state "collapsed" and "expanded" at any time
  • JAWS + Chrome announce the "expanded" state when opening the select pressing Spacebar
  • both switch to "forms mode"
  • on Windows, it's possible to change the options even keeping the select closed: this is standard behavior on Windows
  • when changing options with the select closed, screen readers announce only the option value
  • when the select is open, screen readers announce the option value _and_ their position in the set: n of n

the Deque select:

  • JAWS + Chrome: they announce the initially focused element as "button menu" and the list of options as "listbox"
  • NVDA + Firefox: "button subMenu" and "list"
  • using aria-haspopup="listbox" is a bit arguable, as support is still poor
  • initially, the Deque select doesn't have an aria-expanded attribute: when landing on it, the state is not announced
  • the aria-expanded attribute is set only _after_ the Deque select is opened for the first time
  • with both browser / screen reader combinations, depending also on the navigation mode, either the screen reader never switches to forms mode or it does that only when opening the select

To me, the most important issues are:

  • the difference in the announced role: not sure users will understand what a "button menu" / "button subMenu" is compared to the "combo box" they're used to
  • the lack of the initial expanded state indication: sometimes, aria-expanded is the only clue something is actionable
  • the missing (or quirky) switch to "forms mode"
  • the inability to change the options even with the select closed: this is standard on Windows and expected behavior

All of this demonstrates that, even if well thought and coded:

β€œThe thing is, non-native controls never fully match native element behavior.”
https://twitter.com/ewaccess/status/1157339317142007808

That said, screen readers are just _one_ assistive technology πŸ™‚I'd like to see the Deque select tested at least with a couple more assistive technologies:

  • speech recognition software
  • switch control

Couple screenshots:

Native <select> With Firefox + NVDA:

Screenshot (15)

Deque select With Firefox + NVDA:

Screenshot (14)

@afercia thanks for the thorough review!

To summarize, a custom select should:

  1. announce its role as combobox
  2. annonce expanded/collapsed state
  3. switch to forms mode
  4. change the options even when the select closed (Windows)
  5. announce the option value and their position (n of n)

Would this be a reasonable list of requirements for any custom select to be considered?

@enriquesanchez yes that would be great.

announce its role as combobox

This one is a bit tricky. Browsers (at least Chrome and Firefox) expose a native <select> element with a role combobox, hence screen readers announce it as a combobox. However, the ARIA role combobox has a different meaning (and different expected interaction). Unsure what to do.

Have you tried useSelect() from https://github.com/silviuavram/downshift-hooks ?

Hey @silviuavram! Thanks for the suggestion. I ran a quick test with useSelect():

On Safari + VoiceOver (Mac):

❌ announce its role as combobox
❌ announce expanded/collapsed state β€” _announces collapsed but not expanded_
βœ… switch to forms mode β€” _VO recognizes it as a form element_
~change the options even when the select is closed (Windows)~
βœ… announce the option value and their position (n of n)

Firefox + NVDA (Windows):

❌ announce its role as combobox
βœ… announce expanded/collapsed state
βœ… switch to forms mode
❌ change the options even when the select is closed (Windows)
βœ… announce the option value and their position (n of n)

Also, and while this may be only a styling issue, the element looks like a button instead of a select element.

Thank you @enriquesanchez for the feedback. I'd be happy to follow up on your points. I plan to merge useSelect in Downshift soon, so I am interested in making it ready for production.
https://github.com/downshift-js/downshift

For combobox I am not sure if that is expected. If we are talking about the select widget, then that is different from the combobox one. The combobox always involves an input instead of a button, as it is the case for the select.

For expanded I don't think it's possible to announce expanded state (maybe with Virtual Cursor while the menu is open). By default, normal focus moves to the list after it is open.

For changing the options when the select is closed, I am not sure what you mean. Is this a select feature as well, can you describe it?

You are responsible with the styling, so it is up to you how you do it. But for a select, usually the trigger for the menu is a button. On VoiceOver it is announced as Pop-up button.

Maybe we can sync more on requirements and also if you can provide an example with a fully working widget, anywhere on the internet, maybe that will be helpful as well.

All the best!

Hey @silviuavram!

For combobox I am not sure if that is expected

On Windows, a native select element is announced by screen readers as a combobox. On Mac, it's announced as a popup button

For expanded I don't think it's possible to announce expanded state

I believe it's possible with aria-expanded.

For changing the options when the select is closed, I am not sure what you mean

This is an option available on Windows. You don't need to expand the list of options in order to scroll through the list.

@ItsJonQ has been helping me with the implementation of a custom dropdown/select that covers most of the requirements laid out on this issue.

While there are still some rough edges, we want to hear your feedback. I've been testing it with NVDA+Firefox on Windows and VoiceOver+Safari on Mac and would like to hear from others.

The custom dropdown/select can be found on this Codesandbox: https://2gbb9.csb.app

cc. @afercia

@enriquesanchez that's a great start, thanks! :)
The visuals could be improved, but the fundamental interaction requirements seem well-implemented.

I spotted one bug: when using the up/down arrow keys inside the popup "menu" to select an option from the list of predefined choices, the HTML page scrolls up/down. Missing preventDefault()?
The space bar seems to be handled correctly, as it can be used as an alternative to the enter key, and does not trigger up/down scrolling.

Apple MacOS, Voice Over, Google Chrome web browser:

  • when tabbing into the collapsed "custom font size selector", the current value is not announced.
  • when selecting a value from the popup list using the space bar or the enter key, it is only announced once (subsequent picks are silent)

If implementing it from the ground up is what you wish, sure, go ahead. useSelect just makes it easier, you don't have to do any coding and it can be customisable as well. For instance, if you really want to add role="combobox" and aria-expanded="false" then you are welcome to add it and still get the rest of the hook's functionality.

I did not add those by default because I follow the W3C design pattern for it, and their specs are different.

Thanks for the feedback @danielweck!

We'll make sure to look into the issues you raised.

@enriquesanchez
When using keyboard validation, I noticed you have to use esc to close the select.
In a native select element, it closes directly when you select an item. I think it would be better to at least reproduce the native behavior :)

@audrasjb Thanks for the suggestion! I made that update :)

https://tqujb.csb.app/

Accessibility Testing:

WAVE and AXE automated testing - make sure form/control elements have a label (even if it's visually hidden).

JAWS - Hard to figure out if this is an issue with the version of JAWS I have but it does not identify the selected option so the user is never sure what they selected . Also the available options were not announced. It was never clear what I was accessing or what I could do with it.

The regular HTML select was, not surprisingly, the most accessible and usable in my testing.

I wonder if this might work better as a button that reveals/hides a panel with a radio button list of options inside?

oops! double post!

For changing the options when the select is closed, I am not sure what you mean. Is this a select feature as well, can you describe it?

@silviuavram for what is worth, this WordPress Trac ticket https://core.trac.wordpress.org/ticket/40925 and this short video attached to the ticket https://cloudup.com/iuFxQ7CkA7k may help to understand how on Windows the <select> options can be changed even when the select is closed. That's a standard behavior on Windows.

Thanks @audrasjb and @bemdesign-er for your help testing the component and your feedback.

I'd like to post some testing results, split in comments for each main topic. Before that, please allow me to make some preliminary, important, remarks.

As discussed on Slack, the prevalent opinion in the Accessibility team is to recommend to use a native <select> element. For the many reasons explained on the Slack discussion and on the WPCampus report.

Aslo, as mentioned in a previous comment, some W3C folks are considering to standardise form controls and components to be able (amongst other things) to fully style native <select> elements.

The proposal is included in the Web Incubator Community Group (WICG) and it's in an investigation phase. Ongoing discussion is taking place on the WICG Discourse.

Worth noting that on Windows modern browsers the <select> options can already be styled, to some extent:

select options styled

(selects style-ability exploration by Mason Freed)

Personally, I do believe WordPress is today in a position to participate in the W3C discussion and positively influence the process. I'd like to suggest to the project leads to take into consideration this option, as it seems the best way to improve the web for everyone (a little step at a time).

That said, the Accessibility team aims for a constructive spirit of collaboration across teams and is willing to explore and test all the available options as much as it can.

Basic keyboard interaction on native <select> elements.

  1. keyboard interaction to open a select: how a select opens on different operating systems
  2. keyboard interaction to navigate through the select options: does arrowing loop through the options?

macOS
steps:

  • tab to the native select
  • press Down arrow key
  • the select opens with all tested browsers
  • using Down and Up arrow keys through the options:

Chrome doesn't loop through the options
Firefox doesn't loop
Safari doesn't loop
Opera doesn't loop
Safari + VoiceOver do loop (this seems specific to VoiceOver)

Windows first test
steps:

  • tab to the native select
  • press Down arrow key
  • the select stays closed with all tested browsers
  • using Down and Up arrow keys through the options:

Chrome doesn't loop
Firefox doesn't loop
Edge doesn't loop
Internet Explorer 11 doesn't loop
Opera doesn't loop
Even when using screen readers, there's no loop

Windows second test
steps:

  • tab to the native select
  • press Alt + Down arrow key or Spacebar
  • the select opens with all tested browsers

Same as above: none of the tested browsers loop through the options

Note:
can't test IE11 on the React APP page because of JS errors (see screenshot below) so I've tested it on this page: http://testingwceu2019.altervista.org/wp-content/uploads/2019/08/native-select.htm. Of course, the custom select component should work also with IE 11.

custom select IE errors

Conclusions

These native behaviors need to be replicated in the custom component because that's the keyboard interaction users expect.

On Windows:

  • Down / Up arrow keys don't open the select
  • with the select still closed, Down / Up arrow keys change the options
  • only Alt + Down / Up arrow keys or Spacebar open the select

On macOS:

  • Down / Up arrow keys or Alt + Down / Up arrow keys or Spacebar open the select

On all OSes:

  • when changing options and the last or first option is selected, navigation stops there and doesn't start again from the first / last (no loop)
  • the Tab key doesn't navigate through the options: this must be removed from the custom component current implementation

Note: adding one more option with text "None" to the prototype on https://tqujb.csb.app/ would help testing what happens when typing to select options. The purpose is to have some options that start with the same letters. This addition would be greatly appreciated, when you have a chance πŸ™‚

Type to search and select options (Type-ahead )

On all tested browsers on macOS and Windows, typing the first letters of an option selects the related options. There are minor differences in browsers behaviors but this works everywhere even on IE 11 and a select replacement needs to replicate this native feature as that's the interaction users expect.

Works whether the select is open or closed.
Worth also noting that in this scenario the select stays closed also on macOS.

Testing on http://testingwceu2019.altervista.org/wp-content/uploads/2019/08/native-select.htm

Press the n key
Note: Chrome macOS seems to be a bit slow/buggy and sometimes there's the need to press the n key twice
Note 2: allow for a brief interval between consecutive key presses.

  • tab to the first select
  • press the n key
  • observe that also on macOS the select stays closed
  • the option "Normal" gets selected
  • brief pause
  • press the n key again
  • the option "None" gets selected
  • press the n key again
  • the option "Normal" gets selected again
  • at any press of the n key, the selection loops through "Normal" and "None" (remember to allow for a brief pause)
  • any press of another character moves to the next item with a name that starts with the typed character

Type more than one character

  • tab to the first select
  • type "non"
  • the option "None" gets selected
  • type "la"
  • the option "Large" gets selected
  • type "nor"
  • the option "Normal" gets selected

Repeat the steps above this time opening the select with the Spacebar key first. Basically, the type-ahead behavior is the same as above.

This feature is missing from the current prototype implementation and needs to be added. Basic (non-React) sample core available on the Aria Authoring Practices example: https://www.w3.org/TR/wai-aria-practices-1.1/examples/listbox/listbox-collapsible.html

https://codesandbox.io/s/wordpress-components-dropdown-font-size-picker-uey82

https://uey82.csb.app/

Hello everyone and thank you for your feedback. I released an alpha of downshift with the useSelect hook and created the codesandbox above for testing the Font Picker.

  1. I added as default behavior the selection with the dropdown close, on any character key. Typing n for instance should select Normal then None without opening the menu.
  2. The Windows behavior (selecting with dropdown closed on ArrowDown and ArrowUp) was added by using stateReducer, the way Downshift allows the user to make changes to state before they are actually set. We may add this behavior inside the hook with a parameter, but for now having it in stateReducer is good enough.
  3. Added combobox role to button, by passing it as param to getToggleButtonProps. I really don't agree with it but if that is your requirement then it is possible to add it easily.

I replaced NavigableMenu with ul since that component has some weird behavior on keyDowns. It echoes these events or something, I don't know.

Since the useSelect is still in alpha you can view its Readme here (Pull Request).

At the moment only tested it on MacOS with Chrome, but tomorrow will use other combinations as well. Afterwards will work on getting this PR into the master repo and release a stable version with it.

Try it out and let me know if it works for your scenarios. I will gladly help out with info about the hook functionality or use/code. Good luck!

Hey @silviuavram! πŸ‘‹

I just ran some tests with both VoiceOver and NVDA and it worked really well! Current state, expanded/collapsed, available and selected options are all announced as I was expecting. Keyboard interaction was also as expected πŸŽ‰

I however was not able to interact with it with Dragon Speech. I believe this is because the button is using aria-labelledby and that has weak support with speech recognition apps. According to my tests, if we use aria-label instead, then Dragon Speech can interact with it. I was expecting to be able to say _'Click "Font Size"'_ and have the menu button expand.

Once I tried this change I was able to expand the menu.

Once expanded though, I wasn't able to select an option. If I said _'Click "Huge"'_ for example, the popover will collapse and no change would be registered. This one I'm not sure why is happening. Any clues why?

If we can fix that issue with speech recognition, then I think this component would be in great shape.

Really great testing, @enriquesanchez! Thanks!

While waiting to hear from @silviuavram, can we create a PR with Downshift and make the aria label change ourselves?

cc @enriquesanchez @epiqueras

That is awesome @enriquesanchez thank you for the feedback!

I will get back to this next week as I'm feeling under the weather now.

But yes, you can create the PR. you can remove aria-labelledBy by passing it as undefined to the getToggleButtonProps and passing aria-label instead. Just make sure to do it also in the getMenuProps, that's labelled by the Label as well.

Also make sure you use latest Downshift (3.3.4). Good luck and leave comments here I will address them once I will feel better.

@silviuavram Thanks for all the work here! We're experimenting with this fork: https://codesandbox.io/s/wordpress-components-dropdown-font-size-picker-bwvf2

I however was not able to interact with it with Dragon Speech. I believe this is because the button is using aria-labelledby and that has weak support with speech recognition apps. According to my tests, if we use aria-label instead, then Dragon Speech can interact with it. I was expecting to be able to say 'Click "Font Size"' and have the menu button expand.

This is fixed.

Once expanded though, I wasn't able to select an option. If I said 'Click "Huge"' for example, the popover will collapse and no change would be registered. This one I'm not sure why is happening. Any clues why?

This is still an issue.

Do you have any idea what it might be?

Added a couple of suggestions in the PR @epiqueras

Flagging https://github.com/WordPress/gutenberg/pull/16666 and https://github.com/WordPress/gutenberg/pull/7385 as related here, as they go a different direction with an accessible select menu as they use accessible-autocomplete package.

Looping in @adamsilverstein as he worked on those PRs.

@epiqueras I don't own a license of Dragon Speech (and not really sure if I can get a trial and for which product). Hopefully you can find the issue by stateReducer (the console.log suggestion) and if you need more help let me know!

@silviuavram Me neither, and it's Windows only :cry:

Is there anyone on this thread available for pair programming? :smile:

Is there anyone on this thread available for pair programming? πŸ˜„

With Dragon Home/Speech.*

@grahamarmfield and @ewaccess might be able to help with Dragon, if they have a chance πŸ™‚ They would need a testable page though, not something they need to set up, install pagkaces, etc.

Is there anyone on this thread available for pair programming? πŸ˜„

With Dragon Home/Speech.*

@enriquesanchez did some testing with Dragon on #17418 which was our previous attempt at this.

Looks like the custom select component merged in https://github.com/WordPress/gutenberg/pull/17926 misses a few basic things to be considered a working replacement for _some basic_ (not all) features of a native <select> element.

Most importantly, the currently selected value is not exposed programmatically so any software including screen readers won't be able to understand what the currently selected option is.

  • after a value has been set
  • use a screen reader and navigate to the component button
  • the set value is not announced:

Screenshot 2019-12-03 at 17 49 00

This happens because the button is labelled (actually it's labelled twice) so the label value overrides the button content:

Screenshot 2019-12-03 at 17 50 39

Both the <label> element and the aria-label attribute give the button an accessible name that overrides its content. The button content represents the set value but can't be read out.

Inspecting the accessible properties with Firefox, the relevant difference is that this custom component ha an accessible name but no value:

Screenshot 2019-12-03 at 17 59 34

while a native <select> element has also a value:

Screenshot 2019-12-03 at 17 58 35

Note also the role is different, which may be confusing for users.

At the very least there's the need to:

  1. find a way to make the set value announced

    • maybe aria-describedby could be explored for this purpose

  2. remove the aria-label as there's already a visible associated <label> element

    • aria-label is redundant, unless there's a good reason to keep it I can't think of

Worth also mentioning that native <select> element interaction greatly varies across operating systems and browsers as mentioned in previous comments. Users are used to these interaction models and a select-replacement component simply can't replicate them all. This further increases the chances for potential confusion and unexpected interaction. Personally, I still don't see a good reason to have a custom component only for the sake of a visual preview of the font size, at the cost of losing many of the native features of a native HTML <select>.

Reopening to address the two points above. I'd also like this issue and the implementation from https://github.com/WordPress/gutenberg/pull/17926 to be discussed in the next accessibility team meeting.

aria-label is redundant, unless there's a good reason to keep it I can't think of

We added aria-label after testing with Dragon and verifying that the button would not be activated unless it had the aria-label matching the visible text. It's still open for debate whether it's more intuitive to activate the button by speaking out the label above it or the actual button content though. Perhaps making it equal to the button content would solve the problem?

I'd also like this issue and the implementation from #17926 to be discussed in the next accessibility team meeting.

It would be great to have some more opinions on this! Unfortunately I can't join because the meeting takes place in the middle of the night for me, but more than happy to discuss asynchronously πŸ™‚

Got it. The root problem is:

  • This is still a button that looks like a dropdown (select). While buttons are technically labelable elements, it's very uncommon to have a label associated with a button. Clicking a label should just focus the associated element. In this case instead, clicking the label _activates_ the button
  • The buttons text should always identify the available action (what the button "does). Instead, this button text is the selected value. We've debated at length similar cases, for example the Visibility and Publish date buttons. See https://github.com/WordPress/gutenberg/issues/470 which is open since April 2017 and still to solve because considerations about _visuals_ prevail on standards and semantics. UI controls should just tell what they do. Instead, some UI controls in Gutenberg have text that is the underlying selected setting or state. This is non-standard and goes against basic usability principles.

Overall, even if this component tries to use ARIA techniques it is still a non-native implementation that reduces the accessibility of this control and as such it's actually an accessibility regression compared to the implementation with a native <select> element. A properly labeled <select> element would work for everyone and also with Dragon.

I'd also like to remind the previous implementation with the custom font size selector was flagged as a WCAG failure by the WPCampus audit in https://github.com/WordPress/gutenberg/issues/15319. That's the reason why it was changed to a native <select> following the remediation guidance provided on the issue. There are many non-standard things in this component that it can't be really called "WAI-ARIA compliant custom select" and it will likely be flagged again as a failure by any future accessibility audit.

That said, I do realize others in the team strongly feel in favour of this component because they want a "preview" of the font size. For what is worth, I can't really support this implementation as it comes to a cost of reduced accessibility. I'd like to point out there are other ways to show a preview that haven't been even considered.

@afercia is right, the button being triggered by the label click is an unfortunate side effect.

  • the htmlFor can be removed from the label but the click on the label will not do anything.
  • the button element can be replaced with something else but I don't know what other element can be used to just accept the focus on label click and not be triggered.

Of course a native select will have its accessibility covered out of the box. You will have to spend effort on styling the thing though. Maybe on other things as well.

Do you think of any improvements that can be done here in terms of accessibility?

Do you think of any improvements that can be done here in terms of accessibility?

I'd start strictly following the pattern described on the ARIA Authoring Practices. The patterns described there are the ones assistive technologies are supposed to support.
https://www.w3.org/TR/wai-aria-practices-1.2/#Listbox
https://www.w3.org/TR/wai-aria-practices-1.2/examples/listbox/listbox-collapsible.html

<span id="exp_elem">Choose an element:</span>
<div id="exp_wrapper">
    <button aria-haspopup="listbox" aria-labelledby="exp_elem exp_button" id="exp_button">
        Neptunium
    </button>
    <ul ...

  • there's no <label> element
  • the button is labelled with aria-labelledby which references _two_ elements:

    • the visible text above the button

    • the button itself

This way, also the selected value within the button will be announced by screen readers e.g.: Choose an element: Neptunium

Then, this should be tested again with Dragon and other speech recognition software, e.g. Voice Control / Dictation on macOS.

Still, the different behaviors and interactions across operating systems and browsers can't be covered by a custom component. That's my main concern as they greatly differ and users are used to them.

As I understand the aria-label was added to make it work with Dragon Speech. Originally it should have been only an aria-labelledby with the 2 IDs you correctly mentioned since that's the default useSelect behavior. We can try to remove the aria-label again and dig deeper into why it's not workign.

About the htmlFor I am OK with removing it since it causes this toggle issue. However a native <select> works with a <label> by default. It will just move focus on the <select> without opening it. Do you think it's a good common ground? Removing the htmlFor and adding a onClick on the getLabelProps that will focus() the toggleButton?

About the htmlFor I am OK with removing it since it causes this toggle issue

Removing only the htmlFor would produce an orphaned label, which should be avoided. The whole <label> element should be removed instead.

Yes the aria-labelledby with two IDs should be tested again with speech recognition software but that's the only way I can think of to make assistive technologies announce also the currently selected "option" as they would do with a native <select> element.

The label will not be orphaned, as it will still have the id used in aria-labelledby on the button and menu. So I think we can prop the getLabelProps with {htmFor: undefined} and test it from there. I am pushing for a speech recognition in my org so I can test with that.

Was this page helpful?
0 / 5 - 0 ratings