What package within Headless UI are you using?
@headlessui/vue
What version of that package are you using?
1.7.23 (latest)
What browser are you using?
Safari on iOS
Describe your issue
This looks like the same bug reported for @headlessui/react in #3234 and fixed there in #3801, but the fix never made it into @headlessui/vue.
In packages/@headlessui-vue/src/hooks/document-overflow/handle-ios-locking.ts the touchstart handler on doc decides on every touch whether it started inside an allowed (Dialog) container or not:
d.addEventListener(doc, 'touchstart', (e) => {
if (e.target instanceof HTMLElement) {
if (inAllowedContainer(e.target as HTMLElement)) {
let rootContainer = e.target
while (rootContainer.parentElement && inAllowedContainer(rootContainer.parentElement)) {
rootContainer = rootContainer.parentElement!
}
d.style(rootContainer, 'overscrollBehavior', 'contain')
} else {
d.style(e.target, 'touchAction', 'none')
}
}
})
Once you touch outside the Dialog, touch-action: none gets applied to whatever element was touched and never resets. Because the listener stays on document, later touchstart events keep firing, but nothing clears the previously applied touchAction/overscrollBehavior styles before evaluating the new touch, so scrolling and pinch-zooming inside the Dialog stop working entirely until it's closed and reopened.
I compared this against the current @headlessui/react source for the same file and the fix in #3801 wraps the style side effects in a disposable group and disposes the previous group at the start of every touchstart, so the state gets reset and recomputed each time instead of accumulating. The Vue file I read still has the pre-fix version verbatim, no dispose/reset logic anywhere in that handler.
Reproduction
- Open a
Dialog on iOS Safari.
- Scroll and pinch-zoom inside the Dialog, works fine.
- Tap or scroll once on the page outside the Dialog.
- Try to scroll or pinch-zoom inside the Dialog again, it no longer responds until the Dialog is closed and reopened.
Same repro as #3234, just against @headlessui/vue instead of @headlessui/react.
Expected behavior
Interacting with the Dialog should keep working normally on iOS even after a touch outside it happens, matching the fix already shipped for @headlessui/react in #3801.
What package within Headless UI are you using?
@headlessui/vue
What version of that package are you using?
1.7.23 (latest)
What browser are you using?
Safari on iOS
Describe your issue
This looks like the same bug reported for @headlessui/react in #3234 and fixed there in #3801, but the fix never made it into @headlessui/vue.
In
packages/@headlessui-vue/src/hooks/document-overflow/handle-ios-locking.tsthetouchstarthandler ondocdecides on every touch whether it started inside an allowed (Dialog) container or not:Once you touch outside the Dialog,
touch-action: nonegets applied to whatever element was touched and never resets. Because the listener stays ondocument, latertouchstartevents keep firing, but nothing clears the previously appliedtouchAction/overscrollBehaviorstyles before evaluating the new touch, so scrolling and pinch-zooming inside the Dialog stop working entirely until it's closed and reopened.I compared this against the current @headlessui/react source for the same file and the fix in #3801 wraps the style side effects in a disposable group and disposes the previous group at the start of every
touchstart, so the state gets reset and recomputed each time instead of accumulating. The Vue file I read still has the pre-fix version verbatim, no dispose/reset logic anywhere in that handler.Reproduction
Dialogon iOS Safari.Same repro as #3234, just against @headlessui/vue instead of @headlessui/react.
Expected behavior
Interacting with the Dialog should keep working normally on iOS even after a touch outside it happens, matching the fix already shipped for @headlessui/react in #3801.