fix(dashboard): mobile keyboard scroll lock, auto-reload hash, ChatView snap

- Add useMobileScrollLock hook using position:fixed body lock (Bootstrap/
  Headless UI/Stripe pattern) to prevent iOS Safari from shifting the
  document and visualViewport when an input inside a fixed-position modal
  is focused. Wire into 15 input-bearing modals plus ChatView, replacing
  ChatView's inline body-overflow effect.
- Widen computeBuildVersion in vite.config.ts to hash the entire app/ tree
  so the version-check poll actually notices rebuilds (FN-3333 follow-up;
  previously only main.tsx and package.json were hashed).
- ChatView: on input blur, suppress keyboard-aware sizing for 450ms while
  reserving mobile-nav-bar space, so the composer snaps to its final
  height in one move instead of crawling down with iOS's keyboard slide
  and then jumping again when the nav bar reappears.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-03 19:01:10 -07:00
parent c2f6dd3fbf
commit 08aa64e314
20 changed files with 345 additions and 24 deletions

View File

@@ -0,0 +1,9 @@
---
"@fusion/dashboard": patch
---
Fix mobile keyboard regressions in the dashboard.
- **Dashboard pushed up after closing a modal on mobile.** Adds a shared `useMobileScrollLock` hook that pins `body` with `position: fixed; top: -scrollY; width: 100%` while a fullscreen mobile overlay is open and restores scroll on cleanup — the same pattern Bootstrap, Headless UI, and Stripe Elements use to prevent iOS Safari from scrolling the document (and shifting `visualViewport.offsetTop`) when an input inside a `position: fixed` overlay is focused. Reference-counted so nested overlays don't release each other's locks. Wired into TodoModal, PlanningModeModal, TaskDetailModal, NewTaskModal, SettingsModal, MailboxModal, AddNodeModal, MissionInterviewModal, MilestoneSliceInterviewModal, SubtaskBreakdownModal, GitHubImportModal, AgentGenerationModal, AgentImportModal, ScriptsModal, ResearchTaskActionModal, and ChatView (replacing its inline body-overflow effect).
- **Auto-reload prompt missed rebuilds.** Widens `computeBuildVersion` in `vite.config.ts` to hash the entire `app/` source tree (FN-3333 follow-up). The previous version only hashed `app/main.tsx` and `package.json`, so edits to any other component or stylesheet produced an identical build version and the version-check poll never noticed the rebuild.
- **ChatView composer crawled down with iOS's keyboard-dismiss animation.** On blur, ChatView now suppresses keyboard-aware sizing for ~450ms so the composer snaps back to full height immediately instead of following iOS's slow keyboard slide-out (matches the existing QuickChatFAB behavior).