csandman / chakra-react-select

A Chakra UI themed wrapper for the popular library React Select
https://www.npmjs.com/package/chakra-react-select
MIT License
782 stars 33 forks source link

[BUG] Problem with accessibility of the CreatableSelect (nested interactive elements) #300

Closed vanch3d closed 3 months ago

vanch3d commented 1 year ago

Description

This is a problem with React-Select as well but, given the fact that this is mostly a UI issue being wrapped in Chakra-react-select it might be looked at.

When a CreatableSelect contains values (see the "Select with creatable options" from https://codesandbox.io/s/chakra-react-select-ts-demo-vz9ut?file=/app.tsx), each element has a "clear" button (and, is the isClearable is set, a final "clear" button for remove all values).

The wrapping component gets the focus and selected state, which means it is impossible to use the tab key to navigate to every clear button one by one. In essence, the focus is on the "fake" wrapping input field, at the expense of the internal composition.

This is a potential violation of the nested-interactive rule (WCAG 2.1 (A)), see https://dequeuniversity.com/rules/axe/html/4.3/nested-interactive

A better solution would be to redesign the wrapper, using the approach Chakra uses for the input with an internal button, see https://chakra-ui.com/docs/components/input/usage#password-input-example

chakra-react-select Version

^4.7.6

Link to Reproduction

https://codesandbox.io/s/chakra-react-select-ts-demo-vz9ut?file=/app.tsx

TypeScript?

Steps to reproduce

    <FormControl p={4}>
      <FormLabel>Select with creatable options</FormLabel>
      <CreatableSelect
        isMulti
        name="colors"
        options={groupedOptions}
        placeholder="Select some colors..."
        closeMenuOnSelect={false}
      />
    </FormControl>

Operating System

Additional Information

From https://codesandbox.io/s/chakra-react-select-ts-demo-vz9ut?file=/app.tsx, showing the wrapper with the focus

Screenshot 2023-11-06 at 12 11 19

ChakraUI input showing

Screenshot 2023-11-06 at 12 12 19

Screenshot 2023-11-06 at 12 12 24

It is worth noting that, at the moment, the tab key is mapped to adding the selected option into the input, not to navigate to another UI elements (unless all options have been cleared). #

I accept that there might be no easy way of combining both patterns

csandman commented 1 year ago

First off, I'm not sure what this has to do specifically with the CreatableSelect component. The individual clear buttons always appear whenever you have a select with the isMulti prop.

Second, as far as the Nested Interactive rule is concerned, this pattern doesn't break that rule. Primarily because the actual input component that's focused when you focus the select is a small internal component. The styles that are applied to the outer Control are just the way react-select makes it look like a normal dropdown component.

Also, it is possible to use the keyboard to navigate between the selected options clear buttons to remove them. While the input is focused you can press the left arrow key to navigate through them, and then backspace/delete to remove the option that is currently focused. You can also press delete when nothing is typed to remove the most recently selected options.

As far as native accessibility goes, there isn't really a standard aria pattern in place that this is following, but the core react-select has had issues following native accessibility patterns for a while. There was actually a PR merged in recently to the core package that implements more of the standard combobox pattern aria attributes, which I still need to update this package to support: https://github.com/JedWatson/react-select/pull/5758. The main problem with things like that PR (as you can tell from the description) is that screen readers are not consistent, and it's difficult to make web components be a universally good experience.

But either way, this issue it better off left on the original package. The custom components I made for this package are not actually being rendered by this package, but by react-select itself. That means I have no control over the composition of them, or any of the keyboard interactions.

csandman commented 3 months ago

The accessibility was improved with the changes in react-select@5.8.0 (released in chakra-react-select@4.8.0) so I'm going to mark this as closed.