Further fine tune scroll locking on iOS (#2891)

* further fine tune scroll locking on iOS

* update CHANGELOG
This commit is contained in:
Robin Malfait
2023-12-21 02:49:06 +01:00
committed by GitHub
parent 5976b9a624
commit 20b3b65e76
2 changed files with 19 additions and 21 deletions
+3 -1
View File
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Nothing yet!
### Fixed
- Further fine tune scroll locking on iOS ([#2891](https://github.com/tailwindlabs/headlessui/pull/2891))
## [2.0.0-alpha.2] - 2023-12-20
@@ -95,30 +95,26 @@ export function handleIOSLocking(): ScrollLockStep<ContainerMetadata> {
// Check if we are scrolling inside any of the allowed containers, if not let's cancel the event!
if (e.target instanceof HTMLElement) {
if (inAllowedContainer(e.target as HTMLElement)) {
// We are in an allowed container, however on iOS the page can still scroll in
// certain scenarios...
let rootContainer = e.target
while (
rootContainer.parentElement &&
inAllowedContainer(rootContainer.parentElement)
) {
rootContainer = rootContainer.parentElement!
}
let scrollableParent = rootContainer
// Even if we are in an allowed container, on iOS the main page can still scroll, we
// have to make sure that we `event.preventDefault()` this event to prevent that.
//
// However, if we happen to scroll on an element that is overflowing, or any of its
// parents are overflowing, then we should not call `event.preventDefault()` because
// otherwise we are preventing the user from scrolling inside that container which
// is not what we want.
let scrollableParent = e.target
while (
scrollableParent.parentElement &&
// Assumption that we are always used in a Headless UI Portal. Once we reach the
// portal, its over.
// Assumption: We are always used in a Headless UI Portal. Once we reach the
// portal itself, we can stop crawling up the tree.
scrollableParent.dataset.headlessuiPortal !== ''
) {
// Verify that we are in a scrollable container (which may or may not overflow yet)
let css = window.getComputedStyle(scrollableParent)
if (/(auto|scroll)/.test(css.overflow + css.overflowY + css.overflowX)) {
break
}
// Check if the scrollable container is already overflowing
// Check if the scrollable container is overflowing or not.
//
// NOTE: we could check the `overflow`, `overflow-y` and `overflow-x` properties
// but when there is no overflow happening then the `overscrollBehavior` doesn't
// seem to work and the main page will still scroll. So instead we check if the
// scrollable container is overflowing or not and use that heuristic instead.
if (
scrollableParent.scrollHeight > scrollableParent.clientHeight ||
scrollableParent.scrollWidth > scrollableParent.clientWidth