From 5a3208625c614fe74c6f3d507968be676f08db84 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Sat, 17 Apr 2021 00:45:44 +0200 Subject: [PATCH] Improve search (#385) * make search case insensitive for the listbox * make search case insensitive for the menu --- .../src/components/listbox/listbox.test.tsx | 33 +++++++++++++++++ .../src/components/listbox/listbox.tsx | 2 +- .../src/components/menu/menu.test.tsx | 32 +++++++++++++++++ .../src/components/menu/menu.tsx | 2 +- .../src/components/listbox/listbox.test.tsx | 36 +++++++++++++++++++ .../src/components/listbox/listbox.ts | 2 +- .../src/components/menu/menu.test.tsx | 30 ++++++++++++++++ .../src/components/menu/menu.ts | 2 +- 8 files changed, 135 insertions(+), 4 deletions(-) diff --git a/packages/@headlessui-react/src/components/listbox/listbox.test.tsx b/packages/@headlessui-react/src/components/listbox/listbox.test.tsx index 2f7fac76f3..d70a6e1b89 100644 --- a/packages/@headlessui-react/src/components/listbox/listbox.test.tsx +++ b/packages/@headlessui-react/src/components/listbox/listbox.test.tsx @@ -2764,6 +2764,39 @@ describe('Keyboard interactions', () => { assertActiveListboxOption(options[2]) }) ) + + it( + 'should be possible to search for a word (case insensitive)', + suppressConsoleLogs(async () => { + render( + + Trigger + + alice + bob + charlie + + + ) + + // Focus the button + getListboxButton()?.focus() + + // Open listbox + await press(Keys.ArrowUp) + + let options = getListboxOptions() + + // We should be on the last option + assertActiveListboxOption(options[2]) + + // Search for bob in a different casing + await type(word('BO')) + + // We should be on `bob` + assertActiveListboxOption(options[1]) + }) + ) }) }) diff --git a/packages/@headlessui-react/src/components/listbox/listbox.tsx b/packages/@headlessui-react/src/components/listbox/listbox.tsx index 894ccabc44..a4e9fc6ab0 100644 --- a/packages/@headlessui-react/src/components/listbox/listbox.tsx +++ b/packages/@headlessui-react/src/components/listbox/listbox.tsx @@ -118,7 +118,7 @@ let reducers: { if (state.disabled) return state if (state.listboxState === ListboxStates.Closed) return state - let searchQuery = state.searchQuery + action.value + let searchQuery = state.searchQuery + action.value.toLowerCase() let match = state.options.findIndex( option => !option.dataRef.current.disabled && diff --git a/packages/@headlessui-react/src/components/menu/menu.test.tsx b/packages/@headlessui-react/src/components/menu/menu.test.tsx index 6ecdb96ef1..f8228747f7 100644 --- a/packages/@headlessui-react/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-react/src/components/menu/menu.test.tsx @@ -2408,6 +2408,38 @@ describe('Keyboard interactions', () => { assertMenuLinkedWithMenuItem(items[2]) }) ) + it( + 'should be possible to search for a word (case insensitive)', + suppressConsoleLogs(async () => { + render( + + Trigger + + alice + bob + charlie + + + ) + + // Focus the button + getMenuButton()?.focus() + + // Open menu + await press(Keys.ArrowUp) + + let items = getMenuItems() + + // We should be on the last item + assertMenuLinkedWithMenuItem(items[2]) + + // Search for bob in a different casing + await type(word('BO')) + + // We should be on `bob` + assertMenuLinkedWithMenuItem(items[1]) + }) + ) }) }) diff --git a/packages/@headlessui-react/src/components/menu/menu.tsx b/packages/@headlessui-react/src/components/menu/menu.tsx index e8b65abeb9..d6a09e106c 100644 --- a/packages/@headlessui-react/src/components/menu/menu.tsx +++ b/packages/@headlessui-react/src/components/menu/menu.tsx @@ -97,7 +97,7 @@ let reducers: { return { ...state, searchQuery: '', activeItemIndex } }, [ActionTypes.Search]: (state, action) => { - let searchQuery = state.searchQuery + action.value + let searchQuery = state.searchQuery + action.value.toLowerCase() let match = state.items.findIndex( item => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx b/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx index 16b810186b..286580d929 100644 --- a/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx +++ b/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx @@ -2965,6 +2965,42 @@ describe('Keyboard interactions', () => { assertActiveListboxOption(options[2]) }) ) + + it( + 'should be possible to search for a word (case insensitive)', + suppressConsoleLogs(async () => { + renderTemplate({ + template: html` + + Trigger + + alice + bob + charlie + + + `, + setup: () => ({ value: ref(null) }), + }) + + // Focus the button + getListboxButton()?.focus() + + // Open listbox + await press(Keys.ArrowUp) + + let options = getListboxOptions() + + // We should be on the last option + assertActiveListboxOption(options[2]) + + // Search for bob in a different casing + await type(word('BO')) + + // We should be on `bob` + assertActiveListboxOption(options[1]) + }) + ) }) }) diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.ts b/packages/@headlessui-vue/src/components/listbox/listbox.ts index 73264b3a62..80935e7c56 100644 --- a/packages/@headlessui-vue/src/components/listbox/listbox.ts +++ b/packages/@headlessui-vue/src/components/listbox/listbox.ts @@ -137,7 +137,7 @@ export let Listbox = defineComponent({ if (disabled) return if (listboxState.value === ListboxStates.Closed) return - searchQuery.value += value + searchQuery.value += value.toLowerCase() let match = options.value.findIndex( option => diff --git a/packages/@headlessui-vue/src/components/menu/menu.test.tsx b/packages/@headlessui-vue/src/components/menu/menu.test.tsx index b109344301..13a8d423bc 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-vue/src/components/menu/menu.test.tsx @@ -2454,6 +2454,36 @@ describe('Keyboard interactions', () => { // We should still be on the last item assertMenuLinkedWithMenuItem(items[2]) }) + + it('should be possible to search for a word (case insensitive)', async () => { + renderTemplate(jsx` + + Trigger + + alice + bob + charlie + + + `) + + // Focus the button + getMenuButton()?.focus() + + // Open menu + await press(Keys.ArrowUp) + + let items = getMenuItems() + + // We should be on the last item + assertMenuLinkedWithMenuItem(items[2]) + + // Search for bob in a different casing + await type(word('BO')) + + // We should be on `bob` + assertMenuLinkedWithMenuItem(items[1]) + }) }) }) diff --git a/packages/@headlessui-vue/src/components/menu/menu.ts b/packages/@headlessui-vue/src/components/menu/menu.ts index 9b2b67394e..b2824ca8d6 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.ts +++ b/packages/@headlessui-vue/src/components/menu/menu.ts @@ -104,7 +104,7 @@ export let Menu = defineComponent({ activeItemIndex.value = nextActiveItemIndex }, search(value: string) { - searchQuery.value += value + searchQuery.value += value.toLowerCase() let match = items.value.findIndex( item => item.dataRef.textValue.startsWith(searchQuery.value) && !item.dataRef.disabled