Skip to content

fix(mobile): app-feel pass — kill the website gestures#130

Merged
bndct-devops merged 1 commit into
mainfrom
fix/mobile-app-feel
Jul 18, 2026
Merged

fix(mobile): app-feel pass — kill the website gestures#130
bndct-devops merged 1 commit into
mainfrom
fix/mobile-app-feel

Conversation

@bndct-devops

@bndct-devops bndct-devops commented Jul 18, 2026

Copy link
Copy Markdown
Owner

The PWA felt like a website on phones (reported against Focus mode, but it applied app-wide): you could rubber-band the whole viewport past its edges, double-tap zoom, and long-press-select interface text — and the h-screen shell overhung the visible area behind mobile browser toolbars, which made the page itself pannable.

What

  • html/body: overscroll-behavior: none (no edge bounce, no scroll chaining, no Android pull-to-refresh) + touch-action: manipulation (no double-tap zoom, taps fire without the legacy delay).
  • Touch devices only (@media (pointer: coarse)): user-select: none + -webkit-touch-callout: none on interface chrome; input/textarea/[contenteditable] opt back into text selection. Desktop behavior is completely unchanged.
  • App shells (AppShell, DashboardPage): h-screenh-dvh so the shell matches the visible viewport under mobile browser toolbars; main scrollers get overscroll-contain.

Notes

  • The EPUB reader renders inside its own iframe (foliate), so highlight-by-text-selection is unaffected by the chrome-level user-select: none.
  • Pinch-zoom: the viewport meta (already present) handles Android and the installed iOS app; a regular iOS Safari tab always permits pinch for accessibility — nothing any site can do about that one.
  • The reader already uses fixed inset-0, so it needed no dvh change.

Verification

  • Emulated iPhone 13 viewport: all computed styles land (overscroll-behavior: none, touch-action: manipulation, chrome user-select: none with inputs back to text, main at contain, dvh root exactly matching innerHeight); desktop context confirmed at user-select: auto.
  • Frontend npm run build (tsc) clean.
  • The actual gesture feel (bounce/zoom on real hardware) needs a quick pass on your phone — emulation can't reproduce iOS gesture physics.

Update (551dde1): a screen recording from the real device showed the actual headline symptom — the content area pans sideways and rubber-bands back. Root cause: WebKit counts the Focus rotary's pre-transform 540px stage as scrollable overflow (Chromium uses the post-transform size, which is why emulation initially missed it), giving the main scroller ~150px of horizontal scroll on a phone. Fixed by clamping the app's main scrollers with overflow-x-hidden; verified on Playwright WebKit (iPhone 13 viewport) that scrollLeft is pinned to 0.

…I text selection

The PWA felt like a website on phones: the viewport rubber-banded past its
edges, double-tap zoomed, long presses selected chrome text, and the
h-screen shell overhung the visible area behind mobile browser toolbars,
leaving the page itself pannable.

- html/body: overscroll-behavior none (kills bounce + pull-to-refresh) and
  touch-action manipulation (kills double-tap zoom and its tap delay)
- coarse-pointer only: user-select/touch-callout none on chrome; inputs,
  textareas and contenteditable opt back in. The EPUB reader renders in its
  own iframe, so highlight-by-selection is untouched; desktop is untouched.
- app shells (AppShell, DashboardPage): h-screen -> h-dvh, main scrollers
  get overscroll-contain

Verified computed styles on an emulated iPhone 13 viewport (and desktop
unaffected); gesture feel needs a pass on the real phone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bndct-devops
bndct-devops merged commit 330e532 into main Jul 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant