downshift-js / downshift

🏎 A set of primitives to build simple, flexible, WAI-ARIA compliant React autocomplete, combobox or select dropdown components.
http://downshift-js.com/
MIT License
12.03k stars 931 forks source link

[useSelect]: highlightedIndex vs selectedItem #935

Open stramel opened 4 years ago

stramel commented 4 years ago

This is mostly a question, What is the difference between highlightedIndex and selectedItem, besides the obvious index vs item?

highlightedIndex from the naming would be the item being hovered or focused. However, it seems to mean something more akin to "selectedIndex".

highlightedIndex is used for calculating aria-selected which is even more confusing IMO. I'm unsure how I can tell a hover/highlighted state from an actual selected state since aria-selected is changed to true for any item that is hovered.

I would propose renaming highlightedIndex to selectedIndex and adding a new highlightedIndex that is the actual hover/highlighted state.

I could be misunderstanding or missing how to find the actual selected item though. For now I'm working around it by adding aria-checked={selectedItem && selectedItem === item}.

silviuaavram commented 4 years ago

Unfortunately it is a bit confusing to have aria-selected for the highlighted item, yet that is what ARIA suggests as well.

selectedIndex made sense only if we had multiple selection, and that item was selected along with other ones. In case of multiple selection, ARIA is ok with having aria-selected on selected items.

https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html

jrnail23 commented 3 years ago

I just hit this same issue, and I'm working with a multi-select listbox. @silviuaavram, perhaps useMultipleSelection should handle aria-selected on selected items, shouldn't it? I'd also suggest adding support for aria-multiselectable for the menu element with useMultipleSelection.

silviuaavram commented 3 years ago

Hi @jrnail23 ! I probably can agree with the second part, but not sure about the first part, since you cannot have a selected item element if it's not selected.

Can you provide some documentation / guideline about this? Or maybe some relevant examples? Also please feel free to create a new issue if you think we should try to improve anything.

Thank you!

jrnail23 commented 3 years ago

@silviuaavram, the following is excerpted from WAI-ARIA Roles, States, and Properties of a listbox widget from WAI-ARIA Authoring Practices 1.1:

  • In a single-select listbox, the selected option has aria-selected set to true.
  • if the listbox supports multiple selection:
    • The element with role listbox has aria-multiselectable set to true.
    • All selected options have aria-selected set to true.
    • All options that are not selected have aria-selected set to false.

Also see:

The point here is that the selected options of a dropdown (those options that reflect the value(s) of the "form field"), in general, must have aria-selected="true". In the case of a multi-select, this is independent of focus.

Currently, I have to add custom code to set aria-selected="true" when rendering option elements.

silviuaavram commented 3 years ago

I misunderstood, sorry. I thought you wanted aria-selected on the already selected Tags.

I think we should improve useMultipleSelection.

It should expose getItemProps which should add aria-selected on the selected item, as you requested, if that item is still in the menu and not removed.

I should also work without any selected item Tags, and when navigating Left-Right it should first check if there is a Tag for selected items or not.

A nice to have should be also a getSelectedItemRemoveIcon or something similar to be added to the X icons whose main role would be to remove the item from selection and stop the propagation on click (see useMultipleSelection examples, we do these steps manually).

I am thinking to start working on these and will keep this ticket for tracking. If you have additional feedback please share. Thank you!

domantasjurkus commented 3 years ago

Just wanted to add: based on this WAI-ARIA example, I think the highlighted option should always be selected (in effect, moving the highlight by pressing up/down should automatically select the newly highlighted option): https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html

This is currently not the case in the use-select example in the downshift docs: https://www.downshift-js.com/use-select#basic-usage

Update: just realised this behaviour is OS-dependant. I am on macOS, and while the native <select> does not select the element on highlight, the WAI ARIA example above does - I'm really not sure about the expected behaviour from downshift's perspective 🤔

tpict commented 2 years ago

As far as I can tell, there's only one WAI-ARIA example that

and that's the multiselect listbox, in which aria-activedescendant indicates the highlighted option, and aria-selected indicates selected options.

In all other examples, highlighting an option is equivalent to selecting it. Even in "Combobox with Listbox" example 1, where the widget doesn't visually indicate that an item has been selected on highlight, the only thing that will prevent it from being selected at that point is hitting the "clear input" button or changing the combobox value. That the highlighted option receives aria-selected is probably more indicative of its behavior than what's shown on-screen.

I think this has fueled confusion over what the correct application aria-selected is.

silviuaavram commented 1 year ago

This should be fixed in v7 for useSelect. Will also fix it for useCombobox.

TylerLHenderson commented 2 months ago

This should be fixed in v7 for useSelect. Will also fix it for useCombobox.

Was this fixed in useCombobox?

silviuaavram commented 2 months ago

Once ARIA agrees on moving forward, we will implement their guidance.

https://github.com/w3c/aria-practices/issues/2962