From 1a440e1ee7cf5ce284237b08cf275a06802d2bcb Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Wed, 1 May 2024 15:57:28 -0400 Subject: [PATCH] Fix issues with scrolling in a virtual combobox (#3163) * Scrolling to active option in combobox after opening when last option was selected with the mouse * Allow virtual combobox to scroll freely with mouse wheel after changing options with keyboard * Update changelog --- packages/@headlessui-react/CHANGELOG.md | 1 + .../src/components/combobox/combobox.tsx | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index f8b612ca43..72c81c4918 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix anchored elements not flipping when there is padding ([#3157](https://github.com/tailwindlabs/headlessui/pull/3157)) - Render virtual items during an exiting transition ([#3160](https://github.com/tailwindlabs/headlessui/pull/3160)) - Only render virtual options wrapper when there are items to show ([#3161](https://github.com/tailwindlabs/headlessui/pull/3161)) +- Fix issues with scrolling to / around the active option in a virtual combobox ([#3163](https://github.com/tailwindlabs/headlessui/pull/3163)) ### Changed diff --git a/packages/@headlessui-react/src/components/combobox/combobox.tsx b/packages/@headlessui-react/src/components/combobox/combobox.tsx index 0286b41887..24dcf5a1ff 100644 --- a/packages/@headlessui-react/src/components/combobox/combobox.tsx +++ b/packages/@headlessui-react/src/components/combobox/combobox.tsx @@ -196,6 +196,13 @@ let reducers: { ...state, activeOptionIndex: null, comboboxState: ComboboxState.Closed, + + // Clear the last known activation trigger + // This is because if a user interacts with the combobox using a mouse + // resulting in it closing we might incorrectly handle the next interaction + // for example, not scrolling to the active option in a virtual list + activationTrigger: ActivationTrigger.Other, + __demoMode: false, } }, @@ -1651,6 +1658,12 @@ function OptionsFn( } satisfies OptionsRenderPropArg }, [data]) + // When the user scrolls **using the mouse** (so scroll event isn't appropriate) + // we want to make sure that the current activation trigger is set to pointer + let handleWheel = useEvent(() => { + actions.setActivationTrigger(ActivationTrigger.Pointer) + }) + let ourProps = mergeProps(anchor ? getFloatingPanelProps() : {}, { 'aria-labelledby': labelledBy, role: 'listbox', @@ -1662,6 +1675,7 @@ function OptionsFn( '--input-width': useElementSize(data.inputRef, true).width, '--button-width': useElementSize(data.buttonRef, true).width, } as CSSProperties, + onWheel: handleWheel, }) // Map the children in a scrollable container when virtualization is enabled