ui: prevent layout shift when mobile search overlay opens

- SearchPanel: focus input with { preventScroll: true } so the browser
  doesn't auto-scroll the underlying page when the overlay mounts.
- SearchPanel: add overscroll-contain on the scroll container so
  reaching the panel's edges does not chain into the body on Android.
- PublicLayout: lock background scroll while the mobile search overlay
  is open using the iOS-compatible position-fixed + restore pattern,
  so the page underneath cannot move at all.
This commit is contained in:
TerryM
2026-05-30 01:02:18 +08:00
parent d19f2f9efa
commit cb14cb166a
2 changed files with 35 additions and 2 deletions

View File

@@ -331,6 +331,35 @@ export function PublicLayout() {
};
}, [open]);
// Lock background scroll while the mobile search overlay is open.
// Uses the iOS-compatible position-fixed pattern so the underlying page
// doesn't move at all (overflow:hidden alone is not enough on iOS Safari).
useEffect(() => {
if (!mobileSearchOpen) return;
const scrollY = window.scrollY;
const body = document.body;
const prev = {
position: body.style.position,
top: body.style.top,
left: body.style.left,
right: body.style.right,
width: body.style.width,
};
body.style.position = "fixed";
body.style.top = `-${scrollY}px`;
body.style.left = "0";
body.style.right = "0";
body.style.width = "100%";
return () => {
body.style.position = prev.position;
body.style.top = prev.top;
body.style.left = prev.left;
body.style.right = prev.right;
body.style.width = prev.width;
window.scrollTo(0, scrollY);
};
}, [mobileSearchOpen]);
return (
<div className="min-h-full flex flex-col">
<DocumentMeta />