JedWatson / react-select

The Select Component for React.js
https://react-select.com/
MIT License
27.42k stars 4.1k forks source link

Pressing enter on a button in a custom option component consumes the event before it reaches the custom button. #5930

Closed phazei closed 4 days ago

phazei commented 5 days ago

We're trying to get some buttons we have to be keyboard accessible. It all works via mouse.

We have a custom Option component with an onClick event.

First we needed to be able to tab through all the result items, by setting the options tabSelectsValue: false; menuIsOpen: true it allowed us to do so. When the button inside the option is focused though, and we press enter, nothing happens. It seems that react-select is preventing the onClick event to be passed through. Is there an option to let us manually control what happens when enter is pressed? Can we disable the default "enter" behavior?

phazei commented 4 days ago

So, I realized I could just use the onKeyDown prop, it does trigger when pressing enter on items that were tabbed to. We have a slightly off label use case, where we use it to display an infinite list of search results that's always open. This seems to work pretty well.

{
    const [inputValue, setInputValue] = useState('')

    /**
     * This is useful for when the react-select element is only being used for searching
     * Otherwise since no item is selected, when clicking away from the search, the value
     * typed in will go away.
     */
    const onInputChange = (textInput, { action }) => {
        if (action === 'input-change') {
            setInputValue(textInput)
            return textInput
        }
        return inputValue
    }

    return (
            <Select
                key={keyName}

                {...searchOnly && {
                    inputValue: inputValue,
                    onInputChange: onInputChange,
                    tabSelectsValue: false,
                    onKeyDown: (event) => {
                        if (event.key === 'Enter' || event.key === ' ') {
                            // Manually trigger click
                            const focusedOption = event.target as HTMLElement
                            if (focusedOption) {
                                focusedOption.click()
                            }
                        }
                    }
                }}

                className={classNames('react-select', className)}
                classNamePrefix="select"

                // @ts-expect-error A string still works eg: calc(100vh - 100px)
                maxMenuHeight={maxMenuHeight}

                {...otherProps}
            />
    )
}