-
Notifications
You must be signed in to change notification settings - Fork 933
-
Notifications
You must be signed in to change notification settings - Fork 933
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: multi-select hook for useSelect and useCombobox #879
Comments
Hi! Currently yes, multiple selection is something a user should do by himself. Having a stateful value of A hook to support this out of the box is currently being developed, but it does not guarantee that will cover your use case, as it depends how you will display the selected items. The hook will support the scenario with selected item pills, for instance in the I will use this issue to track this, thanks for pointing it out! Will write the specs in a second comment. |
Long story short, I would like to support this:
Also, an a11y message should be added each time an item has been removed from selection, either on Delete from item or on 'X' icon click. |
Is there an ETA on the |
I'm currently working on a multi select component and would love to try out and test it, I saw there is a PR open where a lot of work has already been done #895 @silviuaavram do you think it's safe to give it a try with the branch Thanks 🙏 |
It's already in 5.1.0-alpha.0 but I forgot to announce it here, my bad! But I would like to make some API changes atm and will push them today. Will also release another alpha. Will let you know! |
Released 5.1.0-alpha.1 with the new changes! |
@silviuaavram where can I have access to 5.1.0-alpha.1? |
@ncesar https://www.npmjs.com/package/downshift/v/5.1.0-alpha.1
|
I will update TS typings as well, right now these are broken for the new
hook, since I did some renames.
…On Wed, 1 Apr 2020 at 22:10, Mattia Asti ***@***.***> wrote:
@ncesar <https://github.com/ncesar>
https://www.npmjs.com/package/downshift/v/5.1.0-alpha.1
npm i ***@***.*** should do it ;)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#879 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACWAZAF26STWCBKWUPP6C2TRKOGT3ANCNFSM4KDRNMGQ>
.
|
Also I would like to ask everyone to open issues on the new hook. It will get released so it's fine to create github issues based on it. Please leave feedback on API, new feature requests and bugs! The earlier the better. I will release this soon and then plan to iterate through all the hooks we have so far in order to improve them. |
Made some more changes on the docs, fixed TS and released https://www.npmjs.com/package/downshift/v/5.1.0-alpha.2. |
Looks good I was able to create a component today A few things I've noticed mostly about TS onStateChange: ({ inputValue, type, selectedItem }) => {
I defined a type for the value (Option) that I have in the items array export type Option = {
label: string
value: string
}
// then TS is complaining here
onSelectedItemsChange: ({ selectedItems: s }: { selectedItems: Option[] }) => onItemsChange(s)
|
@silviuaavram While you're adjusting the TypeScript types, could you please make all the arrays readonly? I use readonly collections everywhere and had to add a hack in my code because Downshift doesn't use readonly arrays, even though AFAIK it doesn't directly mutate them: https://github.com/Daniel15/dnstools/blob/8d6f98ae943bc3ff32587f9289497690eec05520/src/DnsTools.Web/ClientApp/src/components/form/FormRowDropdownList.tsx#L25-L27 |
interface Option {
value: string
id: string
}
const items: Option[] = [
{value: 'test1', id: 'id1'}
]
export default function App() {
useSelect<Option>({items, onSelectedItemChange: ({selectedItem}) => {
console.log(selectedItem && selectedItem.value)
}})
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
} For me this works. What am I missing? |
@silviuaavram you are using Anyway there are 2 issues
const {
isOpen,
getMenuProps,
getInputProps,
getComboboxProps,
highlightedIndex,
getItemProps,
selectItem,
openMenu
} = useCombobox({
itemToString: (i: Option) => i?.label,
inputValue: term,
items,
// TS error here
onStateChange: ({ inputValue, type, selectedItem }) => {
switch (type) {
case useCombobox.stateChangeTypes.InputChange:
setTerm(String(inputValue))
break
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
case useCombobox.stateChangeTypes.InputBlur:
if (selectedItem) {
setTerm('')
addSelectedItem(selectedItem)
selectItem({ label: '', value: '' })
}
break
default:
break
}
}
})
here const {
getSelectedItemProps,
getDropdownProps,
addSelectedItem,
removeSelectedItem,
selectedItems
} = useMultipleSelection<Option>({
initialSelectedItems: initialItems,
// TS error here
onSelectedItemsChange: ({ selectedItems: s }: { selectedItems: Option[] }) => onItemsChange(s)
}) |
Ok, so I see that the typings on those handlers need a bit of work.
I will handle this for useMultipleSelection in the current PR but I think the other ones for the other hooks can be fixed separately. |
I think I found a bug onStateChange: ({ inputValue, type, selectedItem }) => {
switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
} Gonna check the source code now to see if I can catch where the issue is. |
If there is no selection it should not get triggered. The handlers are called only when state changes, the fact that it's |
@silviuaavram understood, thanks for clarifying I'm trying to create a version that gives the user the option to create new items, similar to what gmail does, you can type So far I've been able to do it like this but it's buggy because if I press getDropdownProps({
disabled,
isOpen,
onFocus: () => openMenu(),
onKeyDownCapture: (e: KeyboardEvent) => {
if (creatable && e.keyCode === 13) {
const { value } = e.target as HTMLInputElement
// don't do anything if it's empty
if (!value) {
return
}
// check if it doesn't exist yet
if (!selectedItems.some((i: Option) => i.value === value)) {
addSelectedItem({
label: value,
value
})
setTerm('')
}
}
}
}) Do you have a suggestion? Is this the right approach? Thank you |
Then you need to suppress one of the additions somehow. In the case above which one would you like to be added? Highlighted item or a new element based on the input value? |
If you want the highlighted item, then you can probably skip the Not 100% sure what What do you think? |
Thanks for your reply, appreciate!
That was exactly my issue today, I tried to find a way to not have to use the input manual handler 😄
This might work
This won't work because any value that's included in another will basically break this. |
#985 to fix the typings in |
I'll be able to check on Monday morning 😬 |
@silviuaavram onKeyDownCapture: (e: KeyboardEvent) => {
if (creatable && e.keyCode === 13 && highlightedIndex === -1) {
// user intention
I had a look it seems ok, best to publish it and I can try to see if all good in VSCode 👍 |
Found a possible issue, this is how to reproduce
Bug:
I created a sandbox here to reproduce |
That's expected right? You selected by mouse, why would the keyboard focus
be in the input, probably it's on <body>?
…On Mon, Apr 6, 2020 at 1:35 PM Mattia Asti ***@***.***> wrote:
Found a possible issue, this is how to reproduce
- Press arrow down and select an item from the combobox
- Press enter, the item is selected and added correctly
- The cursor is right after the item
[image: Screen Shot 2020-04-06 at 11 17 35 AM]
<https://user-images.githubusercontent.com/2150927/78548176-3c91bc00-77f8-11ea-9b32-5c1182085526.png>
- Press backspace and the item is removed correctly
Bug:
- Select with the mouse an item from the combobox and click
- The item is correctly added
- Now if you try to use backspace to remove the item you can't
I created a sandbox here to reproduce
https://codesandbox.io/s/ecstatic-driscoll-scdyc
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#879 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACWAZABJZC7G7SDVH7TUJPTRLGV6TANCNFSM4KDRNMGQ>
.
|
I think the focus is indeed correct but if I manually click on the input now the focus is on the input and I would expect to be able to press backspace to remove the last added item and so on. This doesn't happen right now, basically once you have selected an item with the mouse the only way to remove it is by pressing the X icon next to it as the backspace doesn't work anymore. |
I am still thinking about how to properly expose this as API. I should probably replace If I don't add anything and let the multiple kb navigation work always, it can get a bit messy. If you have item highlighted and press Arrow Left, useCombobox reacts on the blur event and selects the highlighted item. So you basically select highlightedItem + navigate on last selected item. Not really what you want I suppose. I was inspired to use |
Yes now that you tell me I realise that I open the dropdown when clicking on the input field so |
Changed the |
Tested now all seems good, didn't really notice any difference in my implementation 🤔 |
I am pretty happy with the code so far. I expect this to be released tomorrow if there are no other issues. |
🎉 This issue has been resolved in version 5.1.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
@mtt87 do you have any code you can share for the components in that storybook link? |
@tim-phillips If you are looking for a specific component I can share that with you but won't be able to share entire codebase as the repo is company private not open source. |
Is it possible to use the
useSelect
hook for a list that allows selecting multiple options? Is there an example of this? It seems like it only has oneselectedItem
prop that just takes a single item, so it is fine to manage the "currently selected items" state myself?The text was updated successfully, but these errors were encountered: