diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index 09d29090b7..41adfc3863 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Render `` in `Popover.Group` component only ([#2634](https://github.com/tailwindlabs/headlessui/pull/2634)) - Disable smooth scrolling when opening/closing `Dialog` components on iOS ([#2635](https://github.com/tailwindlabs/headlessui/pull/2635)) - Don't assume `` components are available when setting the next index ([#2642](https://github.com/tailwindlabs/headlessui/pull/2642)) +- Fix incorrectly focused `Combobox.Input` component on page load ([#2654](https://github.com/tailwindlabs/headlessui/pull/2654)) ## [1.7.16] - 2023-07-27 diff --git a/packages/@headlessui-react/src/components/combobox/combobox.tsx b/packages/@headlessui-react/src/components/combobox/combobox.tsx index 4181ff26c2..d551fc9207 100644 --- a/packages/@headlessui-react/src/components/combobox/combobox.tsx +++ b/packages/@headlessui-react/src/components/combobox/combobox.tsx @@ -53,6 +53,7 @@ import { useControllable } from '../../hooks/use-controllable' import { useWatch } from '../../hooks/use-watch' import { useTrackedPointer } from '../../hooks/use-tracked-pointer' import { isMobile } from '../../utils/platform' +import { useOwnerDocument } from '../../hooks/use-owner' enum ComboboxState { Open, @@ -738,6 +739,7 @@ function InputFn< let actions = useActions('Combobox.Input') let inputRef = useSyncRefs(data.inputRef, ref) + let ownerDocument = useOwnerDocument(data.inputRef) let isTyping = useRef(false) @@ -799,6 +801,11 @@ function InputFn< if (isTyping.current) return if (!input) return + // Bail when the input is not the currently focused element. When it is not the focused + // element, and we call the `setSelectionRange`, then it will become the focused + // element which may be unwanted. + if (ownerDocument?.activeElement !== input) return + let { selectionStart, selectionEnd } = input // A custom selection is used, no need to move the caret @@ -811,7 +818,7 @@ function InputFn< input.setSelectionRange(input.value.length, input.value.length) }) }, - [currentDisplayValue, data.comboboxState] + [currentDisplayValue, data.comboboxState, ownerDocument] ) // Trick VoiceOver in behaving a little bit better. Manually "resetting" the input makes VoiceOver diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md index c50764a852..0d08b0dad1 100644 --- a/packages/@headlessui-vue/CHANGELOG.md +++ b/packages/@headlessui-vue/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Disable smooth scrolling when opening/closing `Dialog` components on iOS ([#2635](https://github.com/tailwindlabs/headlessui/pull/2635)) - Don't assume `` components are available when setting the next index ([#2642](https://github.com/tailwindlabs/headlessui/pull/2642)) - Improve SSR of the `Disclosure` component ([#2645](https://github.com/tailwindlabs/headlessui/pull/2645)) +- Fix incorrectly focused `ComboboxInput` component on page load ([#2654](https://github.com/tailwindlabs/headlessui/pull/2654)) ## [1.7.15] - 2023-07-27 diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts index 88e0fa2ff4..18baa4140d 100644 --- a/packages/@headlessui-vue/src/components/combobox/combobox.ts +++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts @@ -38,6 +38,7 @@ import { useControllable } from '../../hooks/use-controllable' import { useTrackedPointer } from '../../hooks/use-tracked-pointer' import { isMobile } from '../../utils/platform' import { disposables } from '../../utils/disposables' +import { getOwnerDocument } from '../../utils/owner' function defaultComparator(a: T, z: T): boolean { return a === z @@ -700,6 +701,7 @@ export let ComboboxInput = defineComponent({ }, setup(props, { emit, attrs, slots, expose }) { let api = useComboboxContext('ComboboxInput') + let ownerDocument = computed(() => getOwnerDocument(dom(api.inputRef))) let isTyping = { value: false } @@ -743,7 +745,7 @@ export let ComboboxInput = defineComponent({ // - By pressing `escape` // - By clicking `outside` of the Combobox watch( - [currentDisplayValue, api.comboboxState], + [currentDisplayValue, api.comboboxState, ownerDocument], ([currentDisplayValue, state], [oldCurrentDisplayValue, oldState]) => { // When the user is typing, we want to not touch the `input` at all. Especially when they // are using an IME, we don't want to mess with the input at all. @@ -766,6 +768,11 @@ export let ComboboxInput = defineComponent({ if (isTyping.value) return if (!input) return + // Bail when the input is not the currently focused element. When it is not the focused + // element, and we call the `setSelectionRange`, then it will become the focused + // element which may be unwanted. + if (ownerDocument.value?.activeElement !== input) return + let { selectionStart, selectionEnd } = input // A custom selection is used, no need to move the caret