Skip to content

🤖 fix: allow zoom, and keep phone text fields at 16 px so iOS does not zoom on focus - #5992

Merged
ThomasK33 merged 3 commits into
mainfrom
a11y/viewport-zoom-5972
Oct 10, 2026
Merged

ThomasK33 merged 3 commits into
mainfrom
a11y/viewport-zoom-5972

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Summary

The app's viewport meta blocked pinch zoom, so users with low vision could not enlarge text, and Lighthouse failed meta-viewport. This PR removes the zoom lock. iOS Safari zooms the page when a text field with text smaller than 16 px gets focus, and the zoom lock had suppressed that. So this PR also raises text fields to 16 px on phone-width touch screens. Desktop does not change.

Fixes #5972

Changes

  1. index.html: the viewport content drops maximum-scale=1.0 and user-scalable=no. It keeps width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content.
  2. globals.css, in a new block (pointer: coarse) and (max-width: 768px), (pointer: coarse) and (orientation: landscape) and (max-height: 500px): the width branch covers phones in portrait, and the height branch covers phones in landscape, which are wider than 768 px. The existing (max-width: 768px) and (pointer: coarse) block keeps its scope.
    • --min-text-entry-font-size: 16px is defined there, so it does not exist on desktop.
    • One rule sets text-entry fields to that size: input without a type and with types text, search, email, url, tel, password and number, plus textarea, select and contenteditable. Buttons, checkboxes, radios and ranges are not affected.
    • The rule sits outside Tailwind's layers, so it beats text-xs and text-sm classes.
    • Fields with a larger size class (text-lg up to text-3xl) are skipped, so they keep their size. max(16px, 1em) cannot do this: inside font-size, 1em is the parent's size, and in Chromium it shrank the 18 px workspace-name input to 16 px.
  3. VimTextArea.tsx (the composer): the composer sets its size as an inline style, which beats any stylesheet rule. Its ghost-hint overlay copies that style to stay aligned. The inline size is now max(13px, var(--min-text-entry-font-size, 0px)). On desktop the variable is undefined, so the composer stays at 13 px. The style object keeps the same keys.

Validation

  • viewportHeight.test.ts gains "lets users zoom the page". It reads the viewport meta from index.html and fails if user-scalable is no or 0, or if maximum-scale is below 5. It fails on main. Adding maximum-scale=1.0 alone, or user-scalable=0 alone, makes it fail. maximum-scale=5 passes.
  • Font sizes: I used Playwright Chromium at 390x844 with touch emulation (isMobile, hasTouch), and (max-width: 768px) and (pointer: coarse) matched. I measured every visible text field on the seeded workspace, the command palette, all 16 Settings sections, the forms behind "Add" buttons in Providers, Models, Plugins and Layouts, the first-run wizard and the project creation page. Both runs found the same 31 fields. Before this PR, 30 were below 16 px. After it, none are. The 18 px workspace-name input keeps its size.
  • Layout at 390 px: the composer grows from 51 to 60 px for two lines, with nothing clipped. Settings > Models and Settings > Backup do not become wider than the viewport (I did not check the width of the other sections). The palette input is slightly taller, and the palette shows the same 6 results.
  • Desktop: the seeded page at 1280 px, and at 390 px with a mouse (fine pointer), is pixel-identical before and after. The composer stays at 13 px.
  • make static-check passes. make check-react-compiler reports 23/24 (the 1 known skip is ProjectSidebarInner).

Limits

  • An arbitrary size class on a field would be lowered. A field with a class such as text-[18px] would get 16 px on phone-width touch screens. No field uses one today.
  • Not every form was measured. The Secrets add form, the Runtimes forms, and the sidebar rename and search popovers were not reached. The global rule applies to them unless a field sets its size inline.
  • The height branch is not a device filter. Short touch windows and tablet split views below 500 px tall in landscape also get 16 px fields. iPads in landscape are taller, so they do not match.
  • The 16 px rule is tested statically, not by rendering. Neither Pixel nor the Storybook test-runner matches pointer: coarse, so ordinary Pixel snapshots cannot show the rule. The App/TouchTextFields/Contract story reads the shipped rule from CSSOM instead, like coarsePointerMinHeight in App.phoneViewports.stories.tsx. It checks both media branches, the 16px minimum, which fields the selector matches (composer, palette, compact Settings inputs, a type-less input) and skips (the 18 px workspace-name input), and that the composer's inline max() resolves to 16px once the variable is set. Reverting each part of the fix makes it fail. Real touch emulation in the Storybook runner was tried and not used: Chromium keeps (hover: none) after touch emulation is turned off, so touched stories would need their own file, isolated from every other story.
  • The iOS behavior is not verified on a device. Focus zoom below 16 px is documented WebKit behavior. I did not test it on an iPhone.

#5995 tracks the device checks this PR could not run (the terminal's contenteditable root, the unmeasured forms, a real iPhone). #5993 tracks an unrelated flaky E2E test (remoteConnection.spec.ts clipboard permission) that failed once on this PR and passed on rerun.

Screenshots

390 px with touch emulation, before on the left, after on the right.

Composer:

Composer before and after

Command palette:

Command palette before and after

Settings > Models:

Settings Models before and after

Settings > Backup:

Settings Backup before and after


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $43.79

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-10T00:37:39.015899Z e8a40ab New commits
🔒 Security Review ✅ Completed 2026-10-10T00:37:15.984629Z e8a40ab New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1411e9995e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/styles/globals.css
Comment thread src/browser/styles/globals.css
@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit 8eaf829 Oct 10, 2026
31 checks passed
@ThomasK33
ThomasK33 deleted the a11y/viewport-zoom-5972 branch October 10, 2026 01:03
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.

🤖 a11y: the viewport meta blocks zoom (Lighthouse meta-viewport)

1 participant