diff --git a/src/lib/components/listbox/Listbox.svelte b/src/lib/components/listbox/Listbox.svelte index 89ab4314..ff70458f 100644 --- a/src/lib/components/listbox/Listbox.svelte +++ b/src/lib/components/listbox/Listbox.svelte @@ -139,14 +139,22 @@ searchQuery += value.toLowerCase(); - let match = options.findIndex( + let reorderedOptions = + activeOptionIndex !== null + ? options + .slice(activeOptionIndex + 1) + .concat(options.slice(0, activeOptionIndex + 1)) + : options; + + let matchingOption = reorderedOptions.find( (option) => !option.dataRef.disabled && option.dataRef.textValue.startsWith(searchQuery) ); - if (match === -1 || match === activeOptionIndex) return; - activeOptionIndex = match; + let matchIdx = matchingOption ? options.indexOf(matchingOption) : -1; + if (matchIdx === -1 || matchIdx === activeOptionIndex) return; + activeOptionIndex = matchIdx; }, clearSearch() { if (disabled) return; diff --git a/src/lib/components/listbox/listbox.test.ts b/src/lib/components/listbox/listbox.test.ts index 8f8f1d11..e8419641 100644 --- a/src/lib/components/listbox/listbox.test.ts +++ b/src/lib/components/listbox/listbox.test.ts @@ -3125,6 +3125,46 @@ describe('Keyboard interactions', () => { assertActiveListboxOption(options[1]) }) ) + + it( + 'should be possible to search for the next occurence', + suppressConsoleLogs(async () => { + render(svelte` + + Trigger + + alice + bob + charlie + bob + + + `) + + // Open listbox + await click(getListboxButton()) + + let options = getListboxOptions() + + // Search for bob + await type(word('b')) + + // We should be on the first `bob` + assertActiveListboxOption(options[1]) + + // Search for bob again + await type(word('b')) + + // We should be on the second `bob` + assertActiveListboxOption(options[3]) + + // Search for bob once again + await type(word('b')) + + // We should be back on the first `bob` + assertActiveListboxOption(options[1]) + }) + ) }) }) diff --git a/src/lib/components/menu/Menu.svelte b/src/lib/components/menu/Menu.svelte index 6aecd0ee..ebe43e2c 100644 --- a/src/lib/components/menu/Menu.svelte +++ b/src/lib/components/menu/Menu.svelte @@ -99,14 +99,22 @@ search(value: string) { searchQuery += value.toLowerCase(); - let match = items.findIndex( + let reorderedItems = + activeItemIndex !== null + ? items + .slice(activeItemIndex + 1) + .concat(items.slice(0, activeItemIndex + 1)) + : items; + + let matchingItem = reorderedItems.find( (item) => item.data.textValue.startsWith(searchQuery) && !item.data.disabled ); - if (match === -1 || match === activeItemIndex) return; + let matchIdx = matchingItem ? items.indexOf(matchingItem) : -1; + if (matchIdx === -1 || matchIdx === activeItemIndex) return; - activeItemIndex = match; + activeItemIndex = matchIdx; }, clearSearch() { searchQuery = ""; diff --git a/src/lib/components/menu/menu.test.ts b/src/lib/components/menu/menu.test.ts index b18cb120..4c0aeb50 100644 --- a/src/lib/components/menu/menu.test.ts +++ b/src/lib/components/menu/menu.test.ts @@ -2682,6 +2682,46 @@ describe('Keyboard interactions', () => { assertMenuLinkedWithMenuItem(items[1]) }) ) + + it( + 'should be possible to search for the next occurence', + suppressConsoleLogs(async () => { + render(svelte` + + Trigger + + alice + bob + charlie + bob + + + `) + + // Open menu + await click(getMenuButton()) + + let items = getMenuItems() + + // Search for bob + await type(word('b')) + + // We should be on the first `bob` + assertMenuLinkedWithMenuItem(items[1]) + + // Search for bob again + await type(word('b')) + + // We should be on the second `bob` + assertMenuLinkedWithMenuItem(items[3]) + + // Search for bob once again + await type(word('b')) + + // We should be back on the first `bob` + assertMenuLinkedWithMenuItem(items[1]) + }) + ) }) })