0
votes

I've got a keyboard accessible custom drop down component here: https://codesandbox.io/s/31440w1vo6

However, when I turn on NVDA or JAWS, the focus movement to the first element in the options list after activating "Select an Allele" no longer occurs.

I'm guessing this has to do with the roles. Currently I have the "Select an Allele" div with a select role, and an aria-expanded and aria-toggled to describe whether it's open. The options have a role of option.

What roles or aria do I need to apply to ensure that focus is moved correctly when a screen reader is being used?

1
Does it works properly with windows' native screen-reader? Because with MacOS' it works well.extempl
Windows Narrator does allow focus to move when the Select an Allele div is activated, but Narrator isn't announcing any of the text for some reason. Which is its own set of problems... In general I think Narrator is a pretty poor screen reader compared to NVDA which is also free. So I'm not necessarily trying to target that. Good to know that VoiceOver works well though!Taylor N
Yes, the only issue it has as for me, as it reads "Aqua Black square, clickable, Azure black square, clickable". So I'd try to put that square styling to the pseudo selector with disabled screen reader.extempl
Yup I noticed that while testing as well. That's an easy fix. Thanks!Taylor N

1 Answers

1
votes

I did some research and testing, and here is the issue: Space/Enter keydown codes are replaced with click event by the screen-reader in the Browse mode. NVDA has the same issue opened here.

For your case, I'd say it could be easily workaround with selecting the first option for all applicable events like this:

    handleOpenOptions = event => {
        switch (event.type) {
            case "click":
                this._handleOpenOptions(event);
                break;
            case "keydown":
                if (event.key === "Enter" || event.key === " ") {
                    this._handleOpenOptions(event);
                }
                break;
            default:
        }
    };

    _handleOpenOptions = event => {
        this.setState(
            () => {
                return {
                    openOptions: !this.state.openOptions,
                    focusedOption: document.activeElement.id
                };
            },
            () => {
                this.arrayOfOptionsRefs[0].focus();
            }
        );
    };

So this will work both with/without a screen reader.

The other option is to force your page to use the application role:

You could use role="application" to forceably disable use of browse mode, but that would mean the user wouldn't be able to use browse mode.

in that case, events should be handled as they triggered.