Skip to content

Mobile: fit the installed app to a phone — display stamp, no zoom, anchored tab bar - #747

Merged
AllTerrainDeveloper merged 2 commits into
trunkfrom
mobile/pwa-fit
Sep 3, 2026
Merged

Mobile: fit the installed app to a phone — display stamp, no zoom, anchored tab bar#747
AllTerrainDeveloper merged 2 commits into
trunkfrom
mobile/pwa-fit

Conversation

@AllTerrainDeveloper

@AllTerrainDeveloper AllTerrainDeveloper commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Why

Installed on an iPhone home screen, OpenStation left a band of nothing under the tab bar, showed a translucent status bar over the shell's top edge, zoomed the page whenever the home search was focused, and let a pinch scale the chrome off screen. Nothing in the shell knew it was running as an app, the mobile sheet's glass and shadows were literals outside the palette, and two native windows (Trash, WP Explorer) were laid out for a desktop's width.

What

The display stamp. data-os-display="standalone|browser" on <html>, written by the PHP head stamp before the first paint and kept current by the mode controller (the display-mode: standalone query, or Safari's navigator.standalone). Exposed as wp.os.mode.getDisplay() / isStandalone(). Orthogonal to the mode.

No zoom. Three layers, each covering what the others cannot: maximum-scale=1,user-scalable=no in the shell's viewport meta; src/mode/zoom-guard.ts, cancelling Safari's gesture* events, a two-finger touchmove and a ctrl-wheel while the document is stamped mobile or standalone (never on a desktop in a tab, where zoom is an accessibility affordance); and touch-action: pan-x pan-y on the root plus every kit field at 16px on the phone, through new --os-ui-field-font-size / -compact / --os-ui-field-radius tokens the text field, textarea, tag input and category picker read.

The tab bar hugs the bottom edge. It is position: fixed to the viewport with the home-indicator inset as padding, instead of the shell's last flex child; the shell body keeps its footprint clear. A viewport-sized fixed box is what mobile Safari has ended short of the screen before. --wp-admin--admin-bar--height is 0 on a phone.

One surface with the system. The iOS status bar is opaque black (new filter openstation_pwa_status_bar_style to go back to black-translucent or default); the manifest's colours, the theme-color meta and the splash use the backstop #0c0b0f.

The phone wears the palette. Ten --os-mobile-* tokens in variables.css for the glass, its border, the shadows and the scrims; every --_m-* alias reads a token with the old literal as its floor.

No drag and drop on a phone. One refusal in DragManager.start() covers every shell drag; the three gestures that are not manager sessions refuse it themselves: the dock reorder, the OS file-drop sentinel and manager, WP Explorer's marquee.

Narrow apps. Trash's toolbar takes three rows under a 560px container (type filter scrolling sideways under the search); WP Explorer's preview becomes a bottom sheet under 640px, at most 45% tall, present only while something is selected.

Tests

  • tests/vitest/mode-display.test.ts, zoom-guard.test.ts, mobile-viewport.test.ts (the stylesheet contract: anchoring, touch-action, 16px fields, alias-to-token, container queries, the drag refusals).
  • tests/phpunit/tests/mobileMode.php (display stamp, viewport meta on the shell), openStationPwaStatusBarStyle.php.
  • Full JS suite green; typecheck, lint, phpcs, build green.

Docs

mobile.md (the display, the two system edges, the no-zoom policy, drag off, narrow apps), pwa.md, javascript-reference.md, hooks-reference.md, desktop-themes.md, api-index.md.

Testing on a device

Delete and re-add the home-screen app: iOS captures the status-bar style at install.

🤖 Generated with Claude Code

Open WordPress Playground Preview

AllTerrainDeveloper and others added 2 commits September 3, 2026 15:15
…chored tab bar

The phone layer never knew whether it ran in a tab or as an installed
app, nothing stopped the page from zooming, and the tab bar's bottom
edge was wherever Safari ended the shell's viewport-sized fixed box.

- `data-os-display="standalone|browser"` on <html>, written by the head
  stamp and the mode controller; `wp.os.mode.getDisplay()` / `isStandalone()`.
- No page zoom: `maximum-scale=1,user-scalable=no` in the viewport meta,
  `touch-action: pan-x pan-y` on the root, a zoom guard cancelling the
  pinch while stamped mobile or standalone, and every kit field at 16px
  on the phone through `--os-ui-field-font-size` (+ compact, + radius).
- The tab bar is fixed to the viewport's bottom edge; the shell body keeps
  its footprint clear. The admin-bar height token is 0 on a phone.
- Opaque status bar (`black`, filterable via `openstation_pwa_status_bar_style`);
  manifest colours, theme-color and splash on the backstop.
- The phone's glass, shadows and scrims are `--os-mobile-*` tokens.
- Drag and drop off on a phone: DragManager.start(), dock reorder, the
  OS file-drop sentinel/manager and WP Explorer's marquee refuse it.
- Trash's toolbar and WP Explorer's preview fold under a narrow container.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The thirteen palette tokens minted for the phone layer and the kit
fields had no Legacy entry, so the frozen theme would have handed
each to the brand. Each is answered at the value its consuming rule
falls back to — the pre-brand white glass, the shadows and scrims as
they were, 13px/12px/6px for the fields — and the mobile sheet's
glass fallbacks are moved to the same pre-brand literals, which the
standing rule always asked for. The frozen count rises to 482.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@AllTerrainDeveloper
AllTerrainDeveloper merged commit affd3cf into trunk Sep 3, 2026
5 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the mobile/pwa-fit branch September 3, 2026 14:21
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