Accessibility: no way to clear the selection with a keyboard
Caveat: I'm not an accessibility expert so perhaps there is an alternative mechanism available to clear selections. But the usual way (tabbing to the clear button) is not working.
Reproduction Steps
- open NVDA
- visit https://react-select.com/
- tab to any select example that has a selected item and that is clearable (at the time of this writing the first example satisfies these conditions)
- tab again
Expected Behavior
I would expect Step 4 to focus the "X" that clears the selected option.
Actual Behavior
You can't focus the clear button.
Proposed Solution
Make the clear div a button tag.
Am I Willing To Submit A PR For This?
Yes, absolutely. The company I work for has budget for fixing a11y issues in the open source libraries we use or that we are considering using.
The mechanism for clearing options currently via the keyboard is backspace. However I agree that having a visible control that cannot be focused by tabbing could be confusing for those who are sighted but cannot use a mouse.
Yes, whatever keyboard key we choose (space works for me) we need to give it tabIndex.
would a PR be accepted for this?
Hello @dgreene1 and @LauRoxx,
react-select tries to follow the combobox W3C spec.
The spec dictates the following regarding keyboard interaction or more specific, tabbing:
Tab: The combobox is in the page Tab sequence. Note: The popup indicator icon or button (if present), the popup, and the popup descendants are excluded from the page Tab sequence. source
In other words, sub-components should not be able to be focused by pressing the Tab key.
The intended way to clear the selection using a keyboard is by pressing the Delete key, with Backspace being an alternative (source).
Would a PR be accepted for this?
You can create a PR which changes the div to a button, but that would only be acceptable if it behaves the same as without the PR in regards to default tabbing behavior. It should allow for developing users to change the behavior more easily by omitting relevant props (aria-hidden, tabIndex) instead of recreating the whole component.
@Rall3n I agree to the spec but it’s just sad for the user that it’s a bit confusing. I concede though because following specs allows us to provide a common mental model for users so they can “port” their experiences from one application to another.
FYI, your links to the authoring guide above are stale or wrong so I have it here: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/
thank you for the insight.
On second thought, @Rall3n i just re-read the combo box authoring spec and it refers to the popup button or children of the popup. The clear button is neither of those things. So can you clarify why it would break the spec to make clear tab-able?
Note: The popup indicator icon or [popup indicator] button (if present), the popup, and the popup descendants are excluded from the page Tab sequence.
@dgreene1 I don't believe you should take the absence of these elements from the tab sequence exclusions as meaning they're allowed in the tab sequence. The patterns do not account for a multiselect where selected options are listed outside the listbox. Visually we are showing them as being part of the combobox so I believe @Rall3n is correct in saying they should not be in the tab sequence.
Hi @Rall3n, any further thoughts on whether the change will be incorporated?
The problem is that everything that can be done via the mouse should be supported via the keyboard. Delete/backspace only deletes a single item, so there is no equivalent for the clear button. Our company's internal accessibility review has also flagged that fact that the clear button is not keyboard accessible.
I disagree with @Rall3n's & agree with @dgreene1's interpretation of the W3C requirements. It is true that the requirements say "The popup indicator icon or button (if present), the popup, and the popup descendants are excluded from the page Tab sequence.", but the clear button is not the popup indicator/button nor is it a popup descendant. The W3C requirements do not include any mention of the clear button, so we can choose to treat it however we want (as long as it is keyboard accessible).
Even if we want to exclude the clear button from the page Tab sequence, we can still make the clear button accessible to keyboard users. This can be achieved by having it accessible via the L/R arrow keys while the tab focus is on the combobox (similar to the behavior of the navigating between the clear buttons of the individually selected items in the multi-select case).
Hi just found this control and its pretty nice, however keyboard navigation for delete and marking etc are really basic for instance I use shift-home and then delete a lot, to quickly mark a line current line when I am typing and I change my mind.
Use case search for a user in a multiselect by name, then decide you want another one, then you do shift-home delete, and start typing again.. Now I need to backspace x times to delete all the characters. I didn't realise how often I use shift-home, delete until it wasn't there in this widget.
Any update on this?
I'm looking into fixing this
@mattotx Perhaps you can make the clear button being keyboard-accessible opt-in behavior.
@mattotx Any update on the fix?
Just to make sure it doesn't get lost in a PR (#5850) that will likely get closed, I wanted to share what was discussed there that is relevant to this topic.
@jossmac found the WCAG spec that addresses keyboard interaction expectations for combobox controls (which is what react-select is):
Escape: Dismisses the popup if it is visible. Optionally, if the popup is hidden beforeEscapeis pressed, clears the combobox.
As far as what is currently implemented at this time in react-select:
-
DELETEandBACKSPACEwill clear input if the popup is not visible. -
DELETEandBACKSPACEwill not clear input if the popup is visible. -
ESCAPEhas no effect on clearing input.
With regard to clearing react-select instances, it's my belief that react-select MUST be updated to support the clearing of input when ESCAPE is pressed when the popup is not visible. This will make it WCAG-compliant and will make the desire to have the clear button be keyboard focusable moot. Which is a good thing considering there is a contingent of people who found that approach undesirable with the argument that adding an additional tab stop to a form creates a bad user experience.
Hope this helps.
I think it's ridiculous that the keyboard accessibility for something as simple as this clear button isn't fixed. But it is relatively easy to fix it with the customization react-select provides. But without actually fixing it in the main build, it makes every use of it broken for marginalized people over someones interpretation of semantics while it would absolutely not hinder anything to simply fix it.
Here's a simple fix:
import { components as reactSelectComponents, ClearIndicatorProps } from 'react-select'
const CustomClear = ({ ...props }: ClearIndicatorProps<unknown, false>) => {
const { selectProps } = props
return (
<>
<button onClick={() => { props.clearValue() }} className='react-select-custom-clear'
aria-label="clear">
<reactSelectComponents.ClearIndicator {...props} />
</button>
</>
)
}
<ReactSelect
isClearable={true}
components={{
ClearIndicator: CustomClear
}}
/>
Just add some :focus-visible styling to the .react-select-custom-clear and it should work as expected.