From 6c984b62008d6bddc635b80dd69f31eabcb1976f Mon Sep 17 00:00:00 2001 From: yiekheng Date: Sun, 3 May 2026 08:12:35 +0800 Subject: [PATCH] fix(web): lock body scroll while modal is open Native in iOS Safari (and a few other browsers) doesn't prevent the page underneath from scrolling when the user scrolls inside the dialog or near its edges. Save and restore body overflow on open/close so the background stays put. Stays correct for stacked dialogs because we save the previous value rather than blanket-reset to ''. --- web/components/confirm-dialog.tsx | 13 +++++++++++++ web/components/form-dialog-shell.tsx | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/web/components/confirm-dialog.tsx b/web/components/confirm-dialog.tsx index 688a936..0034e13 100644 --- a/web/components/confirm-dialog.tsx +++ b/web/components/confirm-dialog.tsx @@ -41,6 +41,19 @@ export default function ConfirmDialog({ } }, [open]); + // Lock body scroll while open. Native doesn't do this in all + // browsers (notably iOS Safari), so background scroll can leak through + // when scrolling on the dialog content. We restore the previous value + // on close so other modals stacking later don't regress this. + useEffect(() => { + if (!open) return; + const previous = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = previous; + }; + }, [open]); + return ( doesn't on iOS Safari). + useEffect(() => { + if (!open) return; + const previous = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = previous; + }; + }, [open]); + return (