diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index 79e3c7b..eea2417 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [internal] Don’t set a focus fallback for Dialog’s in demo mode ([#3194](https://github.com/tailwindlabs/headlessui/pull/3194)) +- Ensure page doesn't scroll down when pressing `Escape` to close the `Dialog` component ([#3218](https://github.com/tailwindlabs/headlessui/pull/3218)) ## [2.0.3] - 2024-05-07 diff --git a/packages/@headlessui-react/src/components/dialog/dialog.tsx b/packages/@headlessui-react/src/components/dialog/dialog.tsx index 958fab3..3032001 100644 --- a/packages/@headlessui-react/src/components/dialog/dialog.tsx +++ b/packages/@headlessui-react/src/components/dialog/dialog.tsx @@ -310,6 +310,21 @@ function DialogFn( if (event.key !== Keys.Escape) return event.preventDefault() event.stopPropagation() + + // Ensure that we blur the current activeElement to prevent maintaining + // focus and potentially scrolling the page to the end (because the Dialog + // is rendered in a Portal at the end of the document.body and the browser + // tries to keep the focused element in view) + // + // Typically only happens in Safari. + if ( + document.activeElement && + 'blur' in document.activeElement && + typeof document.activeElement.blur === 'function' + ) { + document.activeElement.blur() + } + close() })