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