diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md
index 0d55afda70..81ce288d70 100644
--- a/packages/@headlessui-react/CHANGELOG.md
+++ b/packages/@headlessui-react/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix hanging tests when using `anchor` prop ([#3357](https://github.com/tailwindlabs/headlessui/pull/3357))
- Fix `transition` and `focus` prop combination for `PopoverPanel` component ([#3361](https://github.com/tailwindlabs/headlessui/pull/3361))
- Fix outside click in nested portalled `Popover` components ([#3362](https://github.com/tailwindlabs/headlessui/pull/3362))
+- Fix restoring focus to correct element when closing `Dialog` component ([#3365](https://github.com/tailwindlabs/headlessui/pull/3365))
## [2.1.1] - 2024-06-26
diff --git a/packages/@headlessui-react/src/utils/active-element-history.ts b/packages/@headlessui-react/src/utils/active-element-history.ts
index d75dbb3997..1b66e06131 100644
--- a/packages/@headlessui-react/src/utils/active-element-history.ts
+++ b/packages/@headlessui-react/src/utils/active-element-history.ts
@@ -1,4 +1,5 @@
import { onDocumentReady } from './document-ready'
+import { focusableSelector } from './focus-management'
export let history: HTMLElement[] = []
onDocumentReady(() => {
@@ -7,7 +8,21 @@ onDocumentReady(() => {
if (e.target === document.body) return
if (history[0] === e.target) return
- history.unshift(e.target)
+ let focusableElement = e.target as HTMLElement
+
+ // Figure out the closest focusable element, this is needed in a situation
+ // where you click on a non-focusable element inside a focusable element.
+ //
+ // E.g.:
+ //
+ // ```html
+ //
+ // ```
+ focusableElement = focusableElement.closest(focusableSelector) as HTMLElement
+
+ history.unshift(focusableElement ?? e.target)
// Filter out DOM Nodes that don't exist anymore
history = history.filter((x) => x != null && x.isConnected)
diff --git a/packages/@headlessui-react/src/utils/focus-management.ts b/packages/@headlessui-react/src/utils/focus-management.ts
index 7567d656fd..1a39a3b5c4 100644
--- a/packages/@headlessui-react/src/utils/focus-management.ts
+++ b/packages/@headlessui-react/src/utils/focus-management.ts
@@ -5,7 +5,7 @@ import { getOwnerDocument } from './owner'
// Credit:
// - https://stackoverflow.com/a/30753870
-let focusableSelector = [
+export let focusableSelector = [
'[contentEditable=true]',
'[tabindex]',
'a[href]',
diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md
index f5c040b2fc..4927170da8 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
### Fixed
- Cancel outside click behavior on touch devices when scrolling ([#3266](https://github.com/tailwindlabs/headlessui/pull/3266))
+- Fix restoring focus to correct element when closing `Dialog` component ([#3365](https://github.com/tailwindlabs/headlessui/pull/3365))
## [1.7.22] - 2024-05-08
diff --git a/packages/@headlessui-vue/src/utils/active-element-history.ts b/packages/@headlessui-vue/src/utils/active-element-history.ts
index d75dbb3997..1b66e06131 100644
--- a/packages/@headlessui-vue/src/utils/active-element-history.ts
+++ b/packages/@headlessui-vue/src/utils/active-element-history.ts
@@ -1,4 +1,5 @@
import { onDocumentReady } from './document-ready'
+import { focusableSelector } from './focus-management'
export let history: HTMLElement[] = []
onDocumentReady(() => {
@@ -7,7 +8,21 @@ onDocumentReady(() => {
if (e.target === document.body) return
if (history[0] === e.target) return
- history.unshift(e.target)
+ let focusableElement = e.target as HTMLElement
+
+ // Figure out the closest focusable element, this is needed in a situation
+ // where you click on a non-focusable element inside a focusable element.
+ //
+ // E.g.:
+ //
+ // ```html
+ //
+ // ```
+ focusableElement = focusableElement.closest(focusableSelector) as HTMLElement
+
+ history.unshift(focusableElement ?? e.target)
// Filter out DOM Nodes that don't exist anymore
history = history.filter((x) => x != null && x.isConnected)
diff --git a/packages/@headlessui-vue/src/utils/focus-management.ts b/packages/@headlessui-vue/src/utils/focus-management.ts
index 0b68f7dda3..7ac88984d0 100644
--- a/packages/@headlessui-vue/src/utils/focus-management.ts
+++ b/packages/@headlessui-vue/src/utils/focus-management.ts
@@ -4,7 +4,7 @@ import { getOwnerDocument } from './owner'
// Credit:
// - https://stackoverflow.com/a/30753870
-let focusableSelector = [
+export let focusableSelector = [
'[contentEditable=true]',
'[tabindex]',
'a[href]',