mobileShowChat state set on handleSelectConversation (not media query in JS) — CSS handles desktop visibility, state handles mobile routing
100dvh for mobile container height — handles iOS Safari bottom chrome shrinking viewport
keyboardOffset added to useEffect deps in chat-window — triggers auto-scroll when keyboard opens
Serwist v9 uses class constructor not installSerwist — breaking API change from v8
duration
completed_date
tasks_completed
files_changed
6m 15s
2026-03-25
1
12
MOB-03
MOB-06
Phase 8 Plan 02: Mobile Chat UX Summary
One-liner: WhatsApp-style mobile chat with full-screen conversation view, Visual Viewport iOS keyboard handling, and 44px touch targets throughout.
What Was Built
Mobile chat experience where tapping a conversation on small screens shows a full-screen chat view with a back arrow header. The desktop two-column layout is unchanged. The iOS virtual keyboard no longer hides the message input — Visual Viewport API tracks keyboard height and applies it as bottom padding.
Tasks
#
Name
Status
Commit
1
Mobile full-screen chat toggle and Visual Viewport keyboard hook
Complete
acba978
Key Artifacts
packages/portal/lib/use-visual-viewport.ts
Exports useVisualViewport() — listens to visualViewport resize/scroll events and returns the gap between window.innerHeight and the visual viewport (keyboard height). Returns 0 when no keyboard is open.
packages/portal/components/mobile-chat-header.tsx
Exports MobileChatHeader — sticky md:hidden header with ArrowLeft back button (44x44 tap target) and agent name + avatar. Shown only when mobileShowChat is true.
packages/portal/components/mobile-more-sheet.tsx
Exports MobileMoreSheet — bottom drawer for secondary navigation (Billing, API Keys, Users, Platform) with role-based filtering and LanguageSwitcher. Triggered by "More" tab in mobile nav.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Fixed sw.ts — installSerwist renamed to Serwist class in serwist v9
Found during: Task 1 (build verification)
Issue:app/sw.ts was calling installSerwist() which doesn't exist in serwist v9.5.7 — function was replaced with new Serwist() class + addEventListeners() method
Fix: Rewrote sw.ts to use new Serwist({...}).addEventListeners(), added /// <reference lib="webworker" />, declared __SW_MANIFEST type on ServiceWorkerGlobalScope
Files modified:packages/portal/app/sw.ts
Commit: acba978
2. [Rule 3 - Blocking] Created missing mobile-more-sheet.tsx referenced by mobile-nav.tsx
Found during: Task 1 (build verification)
Issue:components/mobile-nav.tsx (created in Phase 08-01) imports MobileMoreSheet from @/components/mobile-more-sheet which didn't exist — TypeScript error
Fix: Created MobileMoreSheet component — bottom drawer with RBAC-filtered navigation items, LanguageSwitcher, and sign-out
3. [Rule 3 - Blocking] Staged mobile-nav.tsx and layout.tsx from Phase 08-01 unstaged changes
Found during: Task 1 (git status review)
Issue:mobile-nav.tsx and dashboard layout.tsx had Phase 08-01 work that was never committed — both referenced MobileMoreSheet and integrated mobile nav into the layout
Fix: Included both files in the task commit alongside the 08-02 changes