downshift
downshift copied to clipboard
Disabled items are highlighted when select is opened with Arrow Up/Down
-
downshift
version: 6.1.3 -
node
version: 14.17.3 -
npm
(oryarn
) version: npm 6.14.13
Relevant code or config
Example taken from my reproduction :
<ul {...getMenuProps()} style={menuStyles}>
{isOpen &&
items.map((item, index) => (
<li
style={{
...(highlightedIndex === index
? {backgroundColor: '#bde4ff'}
: {}),
// First and last elements are disabled
...(index === 0 || index === items.length - 1
? {opacity: 0.6}
: {}),
}}
key={`${item}${index}`}
{...getItemProps({
item,
index,
disabled: index === 0 || index === items.length - 1,
})}
>
{item}
</li>
))}
</ul>
I just consider that my first and last elements in my list are disabled.
What you did: I have a list of items with some of them disabled. I want to navigate through my enabled items only with keyboard.
What happened:
With useSelect
(the only one i use):
When i use my keyboard for navigation, with focus on my Toggle button, if i press Arrow up/down to open the list, first or last element will be highlighted even if it's disabled.
- First, i just open it with my mouse, we can see that the first and last items can't be highlighted
- Then, i open it with Arrow down, first item is highlighted, even if it's disabled
- Same with Arrow up and last item
Reproduction repository:
Here is where i have recorded the video : https://codesandbox.io/s/snowy-cloud-t5zyw?file=/src/hooks/useSelect/basic-usage.js It's a fork of Downshift examples with changes to reproduce on useSelect basic usage example.
Problem description:
Disabled elements should not be highlighted on menu opening with arrow keys
Suggested solution:
The reducer here : https://github.com/downshift-js/downshift/blob/master/src/hooks/useSelect/reducer.js#L42-L63 is using getHighlightedIndexOnOpen
to know which item to highlight on menu opening.
But it returns 0
or items.length - 1
if it doesn't fit with initial
, default
and selectedItem
values : https://github.com/downshift-js/downshift/blob/master/src/hooks/utils.js#L304
Maybe this return should be improved to use getNextNonDisabledIndex
here : https://github.com/downshift-js/downshift/blob/master/src/utils.js#L368-L407 ?
As it's currently done with MenuKeyDownArrowDown
/MenuKeyDownArrowUp
and getNextWrappingIndex
that use getNextNonDisabledIndex
: https://github.com/downshift-js/downshift/blob/master/src/utils.js#L343-L355
Hope the problem is understood, let me know if it's not 🙂
I'm having this issue as well, exactly like you describe.
While it doesn't fix the highlighting issue, at least you can avoid the disabled item being selected by giving Downshift a state reducer that looks like this:
useSelect({
stateReducer: (state, actionAndChanges) => {
// If the item to be selected is disabled, don't select it.
if (actionAndChanges.changes.selectedItem?.disabled) {
return { ...actionAndChanges.changes, selectedItem: state.selectedItem };
}
return actionAndChanges.changes;
}
})
This code snippet relies on having a disabled
property on your items. If you don't, then you will have to figure out if the soon-to-be-selected item is disabled or not some other way.
Duplicate of https://github.com/downshift-js/downshift/issues/1176. Will track it there.