Skip to content

🤖 fix: stop iPad taps from selecting the whole chat pane - #3761

Open
ibetitsmike wants to merge 38 commits into
mainfrom
mike/ipad-chrome-text-selection
Open

🤖 fix: stop iPad taps from selecting the whole chat pane#3761
ibetitsmike wants to merge 38 commits into
mainfrom
mike/ipad-chrome-text-selection

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes accidental whole-chat text selection on iPadOS by applying the existing touch selection guard to all coarse-pointer widths instead of phones only. The disproven JavaScript focus workaround is removed.

Background

The existing guard lived inside @media (max-width: 768px) and (pointer: coarse). iPadOS reports a coarse primary pointer even with a Magic Keyboard trackpad attached, but iPads exceed the phone breakpoint, so the guard never applied there.

Implementation

  • Move the body selection guard to @media (pointer: coarse).
  • Keep editable controls opted back into user-select: text.
  • Keep phone-specific sizing and layout rules width-gated.
  • Remove the mousedown focus workaround and its helper tests.
  • Remove the attempted static selection contract. Correctly modeling all CSS, Tailwind, JSX, CSSOM, and bundler paths was unbounded and created brittle, behavior-neutral failures.

Validation

  • make static-check: passed.

Risks

Touch-primary tablets can no longer select arbitrary transcript text by drag or long-press, matching existing phone behavior. Editable controls and explicit copy actions remain available. Fine-pointer desktop behavior remains selectable.

Mux worked on this PR on Mike's behalf.


Generated with mux • Model: openai:gpt-5.6-sol • Thinking: xhigh

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 4176b9c78b

ℹ️ 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 Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 2a1816d752

ℹ️ 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
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 90f32629d3

ℹ️ 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 Outdated
@ibetitsmike ibetitsmike changed the title 🤖 fix: stop iPad clicks on app chrome from selecting the chat pane 🤖 fix: stop iPad taps from selecting the whole chat pane Jul 30, 2026
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: e7c663ace8

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: fb948595da

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: f3272a521c

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 1dce3acaac

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 025080804b

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 18400eb8fc

ℹ️ 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/touchSelection.test.ts Outdated
Comment thread src/browser/styles/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: c73ce372ff

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 4f684290df

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 4320c36d29

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: cb82ee70c5

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: b47d74ed5e

ℹ️ 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/touchSelection.test.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Tailwind scans files named by @source directives for utility classes,
so a selection class there would compile like one written in TSX. The
opt-in scan now covers those files, keyed by repo-relative path, and
throws on any @source form it cannot model (not, inline, globs,
directories). A path that matches nothing scans as nothing, exactly
as Tailwind treats it.
The arbitrary-value and variable forms (select-[text], select-(--x))
compile to nothing in this Tailwind version, where select-* is a static
utility, but tracking them costs one regex alternative and closes the
gap a Tailwind upgrade would otherwise open. The @apply refusal also
moves from an anchored token match to a contains match, so variant
chains it did not model ([&:hover]:) and important markers
(select-text!, !select-text), which do compile, can no longer hide a
selection utility from it.
Browsers match CSS property names and keyword values ASCII-case-
insensitively, so USER-SELECT: TEXT defeats the guard while a
lowercase-only pattern never collects it. Properties and values are
lowercased at collection, escaped property names (user-sele\63t)
are refused rather than decoded, and the @apply/@source walks accept
any name case. The TSX scan stays case-sensitive on purpose: it
models Tailwind's candidate parser, which compiles SELECT-TEXT and
[USER-SELECT:text] to nothing, only arbitrary-property values keep
their case and those were already matched by wildcard.
A React style object or DOM style assignment puts the declaration on
the element just like a utility class, invisible to both the stylesheet
parse and a class-only scan. The opt-in pattern now matches camelCase
(userSelect, WebkitUserSelect, DOM webkitUserSelect) and kebab-case
string spellings; literal none values and the empty-string reset stay
untracked as suppression, and a value the pattern cannot see counts as
an opt-in so review decides.
cssText and setProperty parse CSS, which is ASCII-case-insensitive, so
USER-SELECT: text in a string overrides the guard while a lowercase-only
alternative never sees it. Each alternative now carries its parser's
case posture: Tailwind candidates and JS property lookups stay
case-sensitive (SELECT-TEXT and [USER-SELECT:text] compile to nothing or
fail the build, style.USERSELECT is inert), and the kebab spellings are
built letter by letter because one regex flag cannot vary per
alternative.
A per-file count cannot tell a reviewed opt-in from a different one
that replaced it in the same file: removing one of ReviewPanel's four
metadata select-all classes while adding select-text to a transcript
container leaves the count at four. Each occurrence is now pinned by
the trimmed line that carries it, so moving, replacing, or editing a
carrying line resubmits it for review, while unrelated edits elsewhere
in the file leave the entry alone. Identity comes from the line's
text, keeping the exact-match posture, no TSX parsing.
ReviewPanel wraps four metadata values in byte-identical divs, so a
carrying line alone cannot tell them apart: moving one to a transcript
container in the same file leaves the multiset unchanged. Each
occurrence is now the carrying line plus the next non-empty line, which
in JSX is the content the opt-in exposes, so identical wrappers are
distinguished by what they make selectable.
One class or id token is not scoping when the element it names wraps
the application: #root contains everything React renders, so
suppressing selection there is app-wide by inheritance. Shell ids are
read from index.html rather than hardcoded, so a renamed or added
container stays covered.
select-none on a control is safe while the same class on the App.tsx
shell disables desktop selection for everything under it, and a static
scan cannot tell those apart from the class name. The untracked
posture held for one direction only as long as no one could name a
broad suppression site; the shell is one, so both directions now go
through the same enumeration machinery: every suppression spelling,
pinned per occurrence with line-plus-content identity, 38 sites across
33 files generated from the current tree.
The class-name scan globbed src/**/*.{ts,tsx}, but Tailwind's automatic
source detection reads far more, including index.html, whose elements
are real DOM the shell id check just made interesting. Hand-listing
that set is another approximation, so the scan now asks
@tailwindcss/oxide (the scanner underneath the declared tailwindcss
packages) for the file list and applies the same patterns to each file.
A source() clause on the Tailwind import would change the scan base, so
it throws until modelled. Three suppression sites outside src/ join the
map (.design-sync previews, vscode's webview.css); index.html is clean
today.
Pinning each site's line text made behavior-neutral refactors
(reordering classes on a line, renaming a nearby expression) fail the
contract, which is the tautological-test shape AGENTS.md forbids. The
enumeration now records only normalized matched tokens per file with a
count: the full Tailwind candidate including variants and important
markers, or the inline property spelling, with quotes, whitespace, and
the =/: difference folded and only the case-insensitive kebab forms
lowercased. Adds, removals, kind and variant changes, and cross-file
moves still fail; moving an already-reviewed token within a file is an
accepted, documented residual, since telling identical tokens apart
needs surrounding text or TSX parsing, and the PR diff shows what a
moved class newly wraps.
The named-utility alternatives dropped important markers and bracketed
variants from the match, so select-text to select-text! or [&:hover]:
variants changed nothing the inventory saw, contradicting its comment.
The variant chain (named or arbitrary) and either important-marker
spelling are now part of the token, which also surfaced that
ReviewPanel's suppression is [&_summary]:select-none, previously
conflated with a bare select-none.
…tors

A single class token does not guarantee component scope: .mobile-layout
sits on the App.tsx application-wide wrapper, so auto-accepting every
one-token selector let a broad suppressor pass. Reading class names out
of shell files cannot classify tokens either (titlebar-drag appears in
App.tsx on a scoped strip), so selectors are now a reviewed enumeration
with the index.html shell ids as a hard floor no entry can override.
Fixtures, Storybook stories, design previews, docs, and the VS Code
webview were scanned as if their text styled the Electron renderer, so
editing a fixture's sample payload failed the contract without any
behavior change. The scan now keeps only sources that can style a
rendered element: the entry HTML files from vite.config.ts and the src
tree minus test/story/fixture conventions. Tailwind's scanner still
supplies the file list, so file discovery stays delegated.
Backend-only src/node, src/cli, and src/desktop were still inventoried,
so a prompt or comment string mentioning select-none there failed the
contract without any renderer change. The scan now covers a reviewed
segment list (browser, common, constants, version). Transitive closure
cannot compute this: src/common runtime-imports @/node in server-only
corners the renderer never reaches, so reachability at segment
granularity would pull node back in. A drift guard extracts the browser
segment's direct runtime imports (type-only statements stripped) and
fails when a segment outside the list appears.
auto is user-select's initial value and resolves through the parent's
used value, and globals.css guard rules are unlayered while utilities
live in @layer utilities, so a normal select-auto cannot override the
guard or the editable opt-backs; adding it is behavior-neutral and
failed the contract anyway. Important-marked forms stay tracked since
author-important utilities beat the unlayered normal guard rules, as do
the inline auto spellings, which sit above every stylesheet rule. The
co-location residual (select-auto outranking a same-element select-all
in compiled order) is documented alongside the token-move residual.
Selection tokens mentioned only in runtime-source comments are behavior-neutral, but the raw matchAll scan treated them as declarations. Parse TypeScript-family sources and remove comments only from syntax-token gaps so strings, regex literals, template text, and JSX text remain visible; strip HTML comments from markup sources. The regression covers URLs in JSX, JSX and template-expression comments, shebangs, regexes, and real selection tokens after comment-like text.
The runtime-source predicate still admitted src/browser/stories helpers and settingsStoryUtils.tsx, so behavior-neutral Storybook changes could alter the golden inventory. Exclude the Storybook directory and the remaining colocated Storybook helper while keeping a real Settings section in the scan.
Renderer-adjacent Markdown, SVG, JSON, and declaration files were still admitted by the selection inventory, so documentation or asset text could change its golden counts without affecting UI behavior. Keep entry HTML explicit, restrict renderer segments to executable JS and TS sources, and preserve positive coverage for TSX and CJS.
Replace the renderer-segment regex with TypeScript AST traversal so comments, strings, and type-only imports do not create false positives while runtime imports, exports, import-equals, dynamic imports, and require calls remain visible. Preserve language-specific empty-import semantics and wrapped literal arguments. Assert fine-pointer selectability for every vendor property the stylesheet parser recognizes.
---

_Generated with `mux` • Model: `openai:gpt-5.6-sol` • Thinking: `xhigh`_

<!-- mux-attribution: model=openai:gpt-5.6-sol thinking=xhigh -->
@ibetitsmike
ibetitsmike force-pushed the mike/ipad-chrome-text-selection branch from fe24921 to 0e215a0 Compare August 4, 2026 10:01
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 0e215a0ca0

ℹ️ 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/touchSelection.test.ts Outdated
Comment thread src/browser/styles/touchSelection.test.ts Outdated
---

_Generated with `mux` • Model: `openai:gpt-5.6-sol` • Thinking: `xhigh`_

<!-- mux-attribution: model=openai:gpt-5.6-sol thinking=xhigh -->
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@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: c63d7e59cb

ℹ️ 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/touchSelection.test.ts Outdated
Comment thread src/browser/styles/touchSelection.test.ts Outdated
Comment thread src/browser/styles/touchSelection.test.ts Outdated
---

_Generated with `mux` • Model: `openai:gpt-5.6-sol` • Thinking: `xhigh`_

<!-- mux-attribution: model=openai:gpt-5.6-sol thinking=xhigh -->
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 33ec94e542

ℹ️ 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".

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