Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple selection support for useComboBox #2140

Open
stephenh opened this issue Jul 22, 2021 · 45 comments
Open

Multiple selection support for useComboBox #2140

stephenh opened this issue Jul 22, 2021 · 45 comments
Labels
enhancement New feature or request rsp:ComboBox

Comments

@stephenh
Copy link

stephenh commented Jul 22, 2021

馃檵 Feature Request

Update useComboBox to support multiple selection.

馃敠 Context

We're building a type-ahead SelectField / MultiSelectField components, both on top of useComboBox and having to support multiple selections is of course making us do some hacky things, b/c it's not really supported.

I.e. we're not passing selectedKey to useComboBox b/c in a multiple selection scenario, the selectedKey could change, and so then odd things happen where useComboBox thinks its not controlled and/or the selectedKey !== inputValue, so it invokes various closing/reset behavior that we didn't mean to trigger.

Obviously this is on us for misusing useComboBox :-D , so just filing a request / wish list for it to get official multiple selection support. Thanks!

@devongovett
Copy link
Member

We call this a tag field - a combination of a tag list and an input kinda like the "to" field in an email app. It's on the roadmap, but not sure when yet. We need to do some a11y research and testing to determine how best to implement it.

@LFDanLu LFDanLu closed this as completed Jul 27, 2021
@stephenh
Copy link
Author

@LFDanLu lazy ask, but is there a ticket created for the tag field that @devongovett mentioned? I'd like to follow it, so that I can see when react-aria lands support for it. Thanks!

@LFDanLu
Copy link
Member

LFDanLu commented Jul 27, 2021

@stephenh I don't believe there is a ticket created for the tag field yet since it is still in its early germination phase unfortunately. https://github.com/adobe/react-spectrum/projects/1 is the best place to look regarding what is currently in flight.

@devongovett
Copy link
Member

Going to keep this ticket open for tracking.

@devongovett devongovett reopened this Jul 29, 2021
@devongovett devongovett added enhancement New feature or request rsp:ComboBox labels Aug 4, 2021
@devongovett
Copy link
Member

More like the second one, the first is only a select not a combobox (no textfield). Think similar to an email entry field like in Gmail. Here's a screenshot of the design from Spectrum that we'd be basing the pattern on:

tag-field_hero_desktop@2x_6md9yFlaUX9BDThTdZNbgC_1611704216000

@ashiskumar-1999
Copy link

@devongovett
If this falls under priority, I can start working on it.

@ashiskumar-1999
Copy link

Hey, @devongovett As I move forward trying to contribute to this task, I'm wondering if this use-case requires us to build another independent component/hook or this functionality could be incorporated into any existing component?

@beamery-tomht
Copy link
Contributor

Is there a way to achieve this behaviour with existing hooks in react-stately and react-aria?

I'm working on a custom component library according to a design system and using react-aria extensively (without spectrum) and a multi-select is a new requirement. It would be great if we could leverage react-aria for this without having to lean on another library or build something from scratch.

From what I can see, some combination of a SelectionManager and ListBox looks like the most suitable approach

@jamesonhill
Copy link

Is there a way to achieve this behaviour with existing hooks in react-stately and react-aria?

I'm working on a custom component library according to a design system and using react-aria extensively (without spectrum) and a multi-select is a new requirement. It would be great if we could leverage react-aria for this without having to lean on another library or build something from scratch.

From what I can see, some combination of a SelectionManager and ListBox looks like the most suitable approach

This also matches my use case. Are we better off building something from scratch or is support for this use case on the near term roadmap?

@crazko
Copy link

crazko commented Jan 14, 2022

Is there a way to achieve this behaviour with existing hooks in react-stately and react-aria?

I'm working on a custom component library according to a design system and using react-aria extensively (without spectrum) and a multi-select is a new requirement. It would be great if we could leverage react-aria for this without having to lean on another library or build something from scratch.

From what I can see, some combination of a SelectionManager and ListBox looks like the most suitable approach

I was facing this problem regarding multiselect as well. Since @react-aria/select and suitable stately hooks do not support multiple selection mode (and I totally get why it is the case), I followed the implementation of the Picker component, re-created hooks to support our needs (multiple selection, searching possibility, clear & select all buttons...) and built a new Select component with them.

So, instead of:

Basically it means a lot of copy-pasting and playing with properties of hooks underneath. Once I became more familiar with the original implementation I found it very flexible and customizable.

@snowystinger
Copy link
Member

Just an FYI that we are also on our way to building what was described in #2140 (comment) This is the PR where TagGroup work has been started
#1922
Once we have that, we'll be able to consider joining it with a combobox or other components to handle multi select

@donaldpipowitch
Copy link

@crazko are your multi select compatible hooks public by any chance?

@crazko
Copy link

crazko commented Jul 14, 2022

@donaldpipowitch let's check example at https://codesandbox.io/s/spectrum-multiselect-9be866-9be866. It is a simplified version of our Select component implementation with support for both single & multiple selection mode.

There's a bug though, which I was not able to find a fix for so far; it is not present in our library. But should give enough input for how this may work.

@donaldpipowitch
Copy link

Thank you very much!

@npearson72
Copy link

npearson72 commented Aug 21, 2022

Wondering if it will be possible to update the input (or contenteditable element) with a mix of values. My use case is an omni-search box that allows users to type random search strings, but as they type a menu can appear to offer them selections for tags, categories, and other meta data fields. If they make a selection (ex: tag), it should appear in the input field where their cursor was, allowing them to continue typing/selecting as they wish from there.

@snowystinger
Copy link
Member

snowystinger commented Aug 21, 2022

If you are using our hooks to make your combobox, this should already be possible. I wouldn't actually update the input for mixed anything, but you could render anything you wanted before or after the combobox, then just make it visually look like it's part of the input.

Combobox has no plans to support multi select. Instead, when multiselecting, remove selected items and put them outside the combobox, just like you're suggesting with the tags.

@npearson72
Copy link

@snowystinger Thanks for the hint. But from what you're describing I'm struggling to understand how a user would interact with the data they've entered.

For example, say they enter the following:

The quick brown fox jumped over the lazy dog

But now they want to change the word "jumped" to "ran". How would it be possible if this was rendered outside of the input field (or contenteditable element)?

@snowystinger
Copy link
Member

snowystinger commented Aug 22, 2022

hmmm have you tried tokenizing to words, and each word is a combobox? because it doesn't seem like the whole thing is one combobox.

I'm not sure the accessibility implications of this approach, but I don't think it fits combobox otherwise at all. This is an, you're off the map, situation.

Keep in mind, this https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ is the aria pattern we have implemented.

A combobox is an input widget with an associated popup that enables users to select a value for the combobox from a collection of possible values.

@npearson72
Copy link

@snowystinger Got it. Thanks for the explanation. I think you're right in that it might be some hybrid pattern. Appreciate your feedback.

@andresgutgon
Copy link

Hi, yesterday I was also looking for this. I was able to do an autocomplete + tags using

  1. useKeyboard
  2. useListBox
  3. useListState

image

Basically I reimplemented useComboBox with those primitives but configuring useListState as multiple to be able to handle multiple selection 馃帀

image

@wporoslo
Copy link

@andresgutgon Could you kindly share your implementation? I'm struggling with this

@andresgutgon
Copy link

It's still in the oven, but when I have time I'll share a sandbox with the parts.

@andresgutgon
Copy link

andresgutgon commented Mar 2, 2023

@wporoslo sorry for the delay. I made a very ugly version of the one we built
image

But the parts necessary to do a combobox + multiple selection are there
https://codesandbox.io/s/sleepy-keller-qjygke?file=/src/App.tsx

Final result on our side 馃帀
image

@wporoslo
Copy link

wporoslo commented Mar 2, 2023

@wporoslo sorry for the delay. I made a very ugly version of the one we built
thank you so much!

@yarastqt
Copy link
Contributor

Is there any status on this issue? This is a very important feature that we are waiting for 馃様

@snowystinger
Copy link
Member

Is there any status on this issue? This is a very important feature that we are waiting for 馃様

Please see the discussion above, it should answer any questions you have as well as how to build your own. If the ask is specifically for a React Spectrum TagField component, that should be moved to a different place. useCombobox is a specific aria pattern that will not be supporting multiple selection on its own.

@amauryfischer
Copy link

Now that Taggroup is released i would love to see a Tagfield / comboBox with multiple selection.
Like "Autocomplete" in material ui.

@tekno0ryder
Copy link

NextUI just dropped their select component and it supports multi selection 馃憦馃徑

@sadeghbarati
Copy link

sadeghbarati commented Jan 27, 2024

This project is using react-aria and has multi-select support


but I'm eager to see it in react-aria-components

@mryechkin
Copy link

This project is using react-aria and has multi-select support

https://project44.github.io/manifest/inputs/mult-combobox

but I'm eager to see it in react-aria-components

Great find! I agree that it would be good to see it in RAC, but that's at least a good reference implementation if someone wants to build their own.

Here's the source code for anyone interested: https://github.com/project44/manifest/tree/main/packages/react/src/components/MultiCombobox

@deltasierra96
Copy link

This project is using react-aria and has multi-select support

but I'm eager to see it in react-aria-components

Thanks for the reference. I don't suppose you were able to replicate such a component with RAC?

@GermanJablo
Copy link

Please see the discussion above, it should answer any questions you have as well as how to build your own. If the ask is specifically for a React Spectrum TagField component, that should be moved to a different place. useCombobox is a specific aria pattern that will not be supporting multiple selection on its own.

This comment left me confused because before you said that:

Once we have that, we'll be able to consider joining it with a combobox or other components to handle multi select

If I understand correctly, this is planned, but it would not be a Combobox functionality but rather a new input type called TagField, is that correct?

If it's a name problem, perhaps this issue could be renamed instead of opening a new one :)

@snowystinger
Copy link
Member

@GermanJablo your assessment is correct. I'm a little wary of changing the name of the issue because people do search for it a lot and if it said "TagField", I fear we'd get a lot of new issues opened.

The only reason for a new issue I feel would be for the React Spectrum implementation, since we'd be building and styling that.
I'm not sure how much needs to be done for RAC. I think it's fairly close already to being possible. Here's a real quick sketch of what it'd take.
https://stackblitz.com/edit/vitejs-vite-iycf5n?file=src%2FApp.tsx,package.json (styling would need updates to make it look all like one input, but is doable already)
Would need to hook up the labels to a group label probably through aria-labelledby. I'm sure there are some other things that need tweaking or adjustments. I think the bigger question will be if anything is actually missing from the components used that prevents this.

@GermanJablo
Copy link

Oh, I understand. This design pattern seems to rely a lot on CSS compared to the rest of the RACs.
Regarding your question, I don't know what might be missing from RAC in terms of structure or a11y, but perhaps the best way to find out is to try to make a styled example.

@ryo-manba
Copy link
Contributor

Hi! I'm interested in this implementation and think having a specification similar to what's detailed in the following issues would be helpful during development.

Currently, it seems there isn't a detailed spec for this component, and I'm eager to learn more about any research or preliminary considerations you might have at this point, even if it's just in note form.

For example, I'm curious about concepts like moving the cursor between tags, as mentioned in Devon's post.

@ryo-manba
Copy link
Contributor

@snowystinger

I think the bigger question will be if anything is actually missing from the components used that prevents this.

There are a few problems with existing hook combinations that I'd like to introduce.

1. Unavailability of isSelected

The current useComboBoxState is designed exclusively for single selections, where isSelected is applied only to the last selected element. This limitation complicates styling based on selection states within a Popover. For example, the following code does not perform as expected.

<ListBoxItem>
  {({isSelected}) => (
    <>
      {isSelected && <CheckmarkIcon />}
      Item
    </>
  )}
</ListBoxItem>

As a workaround, one could manage separate lists for selectable and selected items and reflect changes in real time using a map function. However, this could lead to unnecessary rendering, making it desirable to utilize isSelected effectively.

const list = useListData({initialItems: items})
const selectedList = useListData()
const isSelected = (item) => typeof selectedList.getItem(item.id) !== 'undefined';

<ListBox>
  {list.items.map((item) => (
      <ListBoxItem id={item.id} key={item.id}>
        {isSelected && <CheckmarkIcon />}
        Item
      </ListBoxItem>
  ))}
</ListBox>;

2. Non-Reflective aria-selected in Popover Choices

Specifying selectionMode and selectedKeys in a ListBox does not reflect aria-selected or aria-multiselectable due to the use of the ComboBox context.

<ListBox selectionMode="multiple" selectedKeys={selectedKeys}>

Here are some examples where aria and data attributes are set based on the ComboBox context:

To address these issues, it might be advisable to create dedicated hooks for the TagField, rather than merely relying on the combination of existing hooks.

@snowystinger
Copy link
Member

snowystinger commented Apr 22, 2024

Thanks for having a think about this!

  1. I think this should be a non-issue. We were to remove the selected item from the combobox entirely and place it into the taggroup. Assistive technology wouldn't know how to announce multiple selection in a combobox.
    https://www.w3.org/WAI/ARIA/apg/patterns/combobox/

The value must be one of a predefined set of allowed values ... or an arbitrary value

  1. See #1, theoretically in this case the combobox will never actually have a selected value, since it would be removed and placed in the taggroup

Let us know if you have more questions or think of something else.

@ryo-manba
Copy link
Contributor

@snowystinger

We were to remove the selected item from the combobox entirely and place it into the taggroup.

Is it correct to understand that the drop-down list of the ComboBox will not support use cases where selected items are displayed within the list?

@adobe adobe deleted a comment from chrisFFL Apr 23, 2024
@snowystinger
Copy link
Member

Yes, that's correct

@6thpath
Copy link

6thpath commented Apr 29, 2024

Hi @snowystinger, is there any chance some hook/context like useCollectionDocument, CollectionDocumentContext of Collection could be exported through
react-aria-components, I almost done on creating a select-multiple component except that list-box-item won't show due to these api are not exported
Screenshot 2024-04-30 at 00 42 43

@sadeghbarati
Copy link

Hey @6thpath, could you please share your code on StackBlitz?

We can manually patch react-aria-components for now to export useCollectionDocument and CollectionDocumentContext for further testing

@6thpath
Copy link

6thpath commented May 14, 2024

Hi @sadeghbarati, sorry for the late reply, there're more than useCollectionDocument and CollectionDocumentContext need to be exported, here's the StackBlitz you asked for

https://stackblitz.com/edit/vitejs-vite-bc1x7h

@sadeghbarati
Copy link

sadeghbarati commented May 14, 2024

https://stackblitz.com/github/sadeghbarati/rac-select-multiple
https://stackblitz.com/edit/github-qwxduv (updated)

@stephenh Hit the upload limit in Stackblitz so I create a GitHub repo for creating demo in Stackblitz
I have some errors in your demo even after exporting needed functions/components

Exported functions and components

  • useCollectionDocument
  • CollectionDocumentContext
  • Hidden from utils.tsx
  • removeDataAttributes from utils.tsx
  • useRenderProps from utils.tsx
  • RenderProps and forwardRefType type from utils.tsx

@sadeghbarati
Copy link

@stephenh

https://stackblitz.com/edit/github-qwxduv

I updated the manual package file with the latest changes in main branch, can you guide us here how to use that
select-multiple component?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request rsp:ComboBox
Projects
Status: 鉁忥笍 To Groom
Development

No branches or pull requests