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`
+
+ `)
+
+ // 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])
+ })
+ )
})
})