From 70d68ac4623b318beb3031c30b8c9481a909e090 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 3 May 2026 19:43:14 -0700 Subject: [PATCH] fix(dashboard): apply mobile scroll lock during inline edits, not just modals Inline editing on the dashboard (e.g. TaskCard inline edit) doesn't go through a modal, so it didn't get useMobileScrollLock applied. iOS would shift the visualViewport / window scroll for the focused input and sometimes leave the dashboard pushed up after the keyboard dismissed. App.tsx now activates useMobileScrollLock whenever mobileKeyboardOpen is true (mobile + keyboard up + no modal open). Modals continue to manage their own lock; the hook is reference-counted so they don't conflict. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/dashboard/app/App.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/dashboard/app/App.tsx b/packages/dashboard/app/App.tsx index ccd18c8b0..a0f3fcdd3 100644 --- a/packages/dashboard/app/App.tsx +++ b/packages/dashboard/app/App.tsx @@ -42,6 +42,7 @@ import { useDeepLink } from "./hooks/useDeepLink"; import { useFavorites } from "./hooks/useFavorites"; import { useAuthOnboarding } from "./hooks/useAuthOnboarding"; import { useMobileKeyboard } from "./hooks/useMobileKeyboard"; +import { useMobileScrollLock } from "./hooks/useMobileScrollLock"; import { useSetupReadiness } from "./hooks/useSetupReadiness"; import { useUpdateCheck } from "./hooks/useUpdateCheck"; import { useViewState, type TaskView } from "./hooks/useViewState"; @@ -292,6 +293,12 @@ function AppInner() { // viewport. Without this guard, modal keyboard state leaks into the app-level // layout, causing stale bottom-padding offsets after the keyboard closes. const mobileKeyboardOpen = isMobile && keyboardOpen && !modalManager.anyModalOpen; + // App-level scroll lock for inline editing (TaskCard inline edit, etc.): + // when the keyboard is up outside of any modal, pin the body so iOS can't + // shift the document or visualViewport, and so the dashboard snaps back + // into place when the keyboard dismisses. Modals manage their own lock + // via useMobileScrollLock — the reference-counted hook handles overlap. + useMobileScrollLock(mobileKeyboardOpen); // App-level mailbox unread count state (used for header/mobile nav badges) const [mailboxUnreadCount, setMailboxUnreadCount] = useState(0);