Skip to content

useSelect - NVDA keeps reading out the selected value continuously, even when neither focus is set on the dropdown, nor the dropdown value has changedΒ #1643

@Praneetha-CK

Description

@Praneetha-CK

downshift version: "^8.1.0"

Tools used:
NVDA

Relevant code or config

import React, { forwardRef } from 'react';
import _isEmpty from 'lodash/isEmpty';
import { useSelect } from 'downshift';
import { string, arrayOf, shape, func } from 'prop-types';
import '../Dropdown.scss';
import CheckMarkIcon from '../../../resources/images/checkmark-black.svg';
import { classNames } from '../../../site/helper/utils';

const itemToString = item => {
    return item ? item.title : '';
};

const Downshift = forwardRef(
    (
        {
            className,
            list,
            label,
            field,
            disabled,
            selectedValue,
            handleOnChange,
            errorMessage,
            required,
            id,
            dropdownButtonClassName,
            ...rest
        },
        ref
    ) => {
        const selectedItem = list.find(item => item.value === selectedValue?.value) || null;
        const { isOpen, getToggleButtonProps, getLabelProps, getMenuProps, highlightedIndex, getItemProps } = useSelect(
            {
                items: list,
                selectedItem,
                onSelectedItemChange: ({ selectedItem }) => handleOnChange(selectedItem),
                itemToString,
            }
        );

        const showErrorMsg = !!errorMessage;

        const dropdownList = (
            <ul
                className={classNames( className, !isOpen && 'hidden')}
                {...getMenuProps()}
            >
                {list.map((item, index) => (
                    <li
                        key={item.value}
                        type="button"
                        className={classNames(
                            (selectedItem?.value === item.value || highlightedIndex === index) && 'selected'
                        )}
                        {...getItemProps({ item, index })}
                        data-testid={`dropdown-item-${item.value}`}
                    >
                        {item.title}
                        {selectedItem?.value === item.value && (
                            <img src={CheckMarkIcon} alt="ArrowUpIcon" width={12} height={9} />
                        )}
                    </li>
                ))}
            </ul>
        );

        const dropdownButton = (
            <div
                tabIndex={0}
                type="button"
                className={dropdownButtonClassName}
                disabled={disabled}
                {...getToggleButtonProps({
                    ref,
                })}
                aria-required={required}
                aria-invalid={!!errorMessage}
                data-testid="dropdown-button"
                {...rest}
                id={id}
            >
                {!_isEmpty(selectedItem) ? (
                    <>
                        {
                            <label className="dd-header-title focused" {...getLabelProps()}>
                                {label}
                            </label>
                        }
                        <div className="dd-header-title" data-testid="dropdown-selected-item">
                            {itemToString(selectedItem)}
                        </div>
                    </>
                ) : (
                    <label className="dd-header-title placeholder" {...getLabelProps()}>
                        {label}
                    </label>
                )}

            </div>
        );

    

        return (
            <div id={field} className={className}>
                {dropdownButton}
                {dropdownList}
            </div>
        );
    }
);

Downshift.propTypes = {
    list: arrayOf(
        shape({
            title: string,
            value: string,
        })
    ).isRequired,
    selectedValue: shape({ title: string, value: string }),
    handleOnChange: func.isRequired,
};
Downshift.defaultProps = {
    list: [],
    selectedValue: { title: '', value: '' },
};

export default Downshift;

Issue faced:

I have this dropdown used inside a Form that contains other input text boxes.
When opening form in edit mode, even though focus is not set on the dropdown, it reads out "ABC has been selected", [ABC being here the value set]
I fixed this in Voiceover by programmatically setting focus to first field in the form which happens be an input box, so that way Voiceover is now reading out the 1st focused input and isn't reading dropdown status anymore.

But on NVDA, even after this change, it is now first reading out the programmatically focused input, and again the dropdown value, even though no focus is set on dropdown.

Along with this, when i submit the form, by clicking submit button, it keeps on shouting "ABC has been selected", continuously 2-3 times, until the form is closed, even though value of dropdown hasn't changed OR the focus hasn't been set on dropdown.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions