fix(dashboard): keep Android keyboard open in main chat; disable kanban pinch-zoom
Two Android-specific fixes: 1. Keyboard dismissing in main chat. App.tsx derives `mobileKeyboardOpen` from useMobileKeyboard and uses it to gate the `project-content--with-mobile-nav` / `--with-footer` className assignment plus MobileNavBar rendering. When the soft keyboard opened on Android, those classes were removed and the nav unmounted, shrinking padding-bottom by ~80px in a single render. Android Chrome treats the resulting jump of the focused chat input as the focus target moving and instantly dismisses the keyboard. With interactive-widget=resizes-content set on Android, the layout viewport itself shrinks with the keyboard, so the hide-nav-on-keyboard pattern was redundant on Android (and harmful). The whole pattern is now gated to iOS via isIOS(). iOS path is unchanged. 2. Pinch-zoom on kanban. Android Chrome ignores user-scalable=no for a11y, and kanban's overflow-x:auto columns combined with the inflated ICB produce a broken visual when the user zooms out. Adds touch-action: pan-x pan-y to html,body inside the mobile media query (keeps scroll panning, blocks pinch-zoom). Chat and MissionManager were unaffected before because they don't expose a wide horizontal scrollable region. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
11
.changeset/android-keyboard-and-zoom.md
Normal file
11
.changeset/android-keyboard-and-zoom.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
"@fusion/dashboard": patch
|
||||
---
|
||||
|
||||
fix(dashboard): keep Android keyboard open in main chat; disable kanban pinch-zoom
|
||||
|
||||
Two Android-specific fixes:
|
||||
|
||||
1. **Keyboard dismissing in main chat.** `mobileKeyboardOpen` in `App.tsx` (derived from `useMobileKeyboard`) gates `project-content--with-mobile-nav` / `--with-footer` className assignment and MobileNavBar rendering. When the soft keyboard opened, those classes were removed and the nav unmounted, shrinking padding-bottom by ~80px in a single render. Android Chrome treats the resulting jump of the focused chat input as the focus target moving and instantly dismisses the keyboard. With `interactive-widget=resizes-content` set on Android, the layout viewport itself shrinks with the keyboard, so the hide-nav-on-keyboard behavior was redundant on Android (and harmful). The whole pattern is now gated to iOS via `isIOS()`. iOS path is unchanged.
|
||||
|
||||
2. **Pinch-zoom on kanban.** Android Chrome ignores `user-scalable=no` for accessibility, and the kanban board's `overflow-x: auto` columns combined with the inflated ICB produce a broken visual when the user zooms out. Adds `touch-action: pan-x pan-y` to `html, body` inside the mobile media query, which keeps scroll panning but disables pinch-zoom (Chat and MissionManager were unaffected because they don't expose a wide horizontal scrollable region).
|
||||
@@ -57,7 +57,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 { isIOS, useMobileScrollLock } from "./hooks/useMobileScrollLock";
|
||||
import { useSetupReadiness } from "./hooks/useSetupReadiness";
|
||||
import { useUpdateCheck } from "./hooks/useUpdateCheck";
|
||||
import { useViewState, type TaskView } from "./hooks/useViewState";
|
||||
@@ -463,7 +463,15 @@ function AppInner() {
|
||||
// affecting the underlying dashboard layout — the modal handles its own
|
||||
// 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;
|
||||
//
|
||||
// Android-gated: with `interactive-widget=resizes-content` the layout
|
||||
// viewport itself shrinks with the soft keyboard, so we DON'T want to
|
||||
// also hide the nav bar / strip its padding — that produces a layout
|
||||
// jump while the focused input is settling, which Android Chrome treats
|
||||
// as the focus target moving and dismisses the keyboard immediately.
|
||||
// iOS doesn't shrink the layout viewport, so the iOS path keeps the
|
||||
// hide-nav-on-keyboard behavior intact.
|
||||
const mobileKeyboardOpen = isMobile && keyboardOpen && !modalManager.anyModalOpen && isIOS();
|
||||
// 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
|
||||
|
||||
@@ -21,7 +21,7 @@ function isMobileDevice(): boolean {
|
||||
* Chrome shrinks the layout viewport with the keyboard, so no drift
|
||||
* compensation is needed there.
|
||||
*/
|
||||
function isIOS(): boolean {
|
||||
export function isIOS(): boolean {
|
||||
if (typeof window === "undefined") return false;
|
||||
const ua = navigator.userAgent || "";
|
||||
// iPad on iPadOS 13+ reports as MacIntel + touch — handle that too.
|
||||
|
||||
@@ -3219,6 +3219,11 @@ input[type="range"]:focus-visible {
|
||||
html,
|
||||
body {
|
||||
overflow: hidden;
|
||||
/* Disable pinch-zoom on mobile — Android Chrome ignores user-scalable=no
|
||||
for a11y, and the kanban board's horizontally-scrollable layout
|
||||
interacts badly with zoom-out (exposes the offscreen-right area).
|
||||
`pan-x pan-y` keeps scroll panning but blocks pinch-zoom. */
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
|
||||
#root {
|
||||
|
||||
Reference in New Issue
Block a user