Repository navigation
Conversation
On iOS 26, UIAlertController lays out its text field past the alert's trailing edge, so Alert.prompt-based prompts (Rename thread, Link pull request) render a misaligned input. Present iOS prompts in-app through Dialog.Host instead, keeping native alerts and confirms. A React Native Modal presents from its nearest view controller, which cannot present over a native form sheet, so the PR and git sheets mount their own Dialog.SheetHost; the most recently mounted host presents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the iOS prompt UI into DialogHost so modules that only call Dialog alerts don't pull GlassSurface and native modules into their tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f5fdb9a to
8253ac3
Compare
|
Note Written by updated the original branch at
verification: three callback-timing regression cases failed before the fix. all five dialog tests pass afterward, including the existing android host test. blacksmith unverified: current-main native overflow reproduction, rename, both link-pr sheet prompts, dynamic type, rotation, and matching before/after screenshots/video. device discovery returned "Agent device access is turned off for this environment." the linux browser cannot reproduce UIKit's alert or native sheet lifecycle. no new native evidence was captured; the existing body evidence is from the contributor's older revisions. main still uses the affected keeping this draft pending on-device verification and human approval. web/desktop and provider paths are unchanged; android retains its existing presenter. task-owned dev server and check workers have been stopped. |
Problem
On an iPhone running iOS 26 (Nightly build), the Rename thread prompt rendered its text field shifted past the alert's trailing edge. On the simulator, the same overflow appears when the alert lays out again while open (see Evidence). The field's left edge sits inside the card, but its right side runs past the alert. Every iOS
Dialog.promptuses this alert: Rename thread (thread list context menu) and Link pull request (PR and git sheets). The iOS implementation used React Native'sAlert.prompt, which is a stockUIAlertControllerwithaddTextFieldWithConfigurationHandler, so the layout comes from UIKit and we can't fix it from JS.Repro: on iOS 26 (Nightly), long-press a thread on Home and choose Rename.
Expected: the input sits inside the dialog, like Android's Compose dialog.
Change
Dialog.tsx(iOS):promptnow hands the request to an in-app dialog in the newDialogHost.tsx, mounted at the app root whereDialog.Hostwas. Keeping the UI inDialogHostmeans modules that only callDialog.alertdon't pull native UI modules into their unit tests. The dialog is a transparent fadeModalwith aGlassSurfacecard, anAppTextInput, and Cancel and primary buttons. These are the same building blocks and tokens the command palette uses.alertandconfirmstill use nativeAlert.Modalpresents from its nearest view controller, and the root controller can't present over a native form sheet. So hosts register as a stack: the most recently mounted one presents.ThreadPullRequestsSheetandGitOverviewSheetmountDialogSheetHost, because Link pull request opens from those sheets. On Android,DialogHost.android.tsxre-exports the existing Compose host andDialogSheetHostis a no-op because Compose dialogs open in their own window.Scope and approval
No prior issue. I think this qualifies as a small, focused fix for an obvious visual bug in an existing control, with no change to product behavior. The prompts keep the same callers, options, and callback semantics. The sheet host is only there because the in-app prompt has to present over sheets.
Verification
ea2f2e5, 2026-10-23): retained main's sheet headers/toolbars alongside the dialog sheet hosts and main's test pruning. All three retained dialog tests, mobile typecheck, scoped lint and formatting pass; required hosted checks pass on this commit. Native captures and broader test counts below belong to the explicitly identified earlier revisions. No new native session was run; this PR remains draft pending acceptance.vp test run --project unit --project react): 289 files pass. The newDialogHost.test.tsxcovers that an edited value is confirmed exactly once under a double tap, and that a mounted sheet host presents before the root host, falling back to the root host after the sheet unmounts. The existing Android dialog test still passes.tsc-rs --noEmitinapps/mobileis clean.vp lintreports no new warnings. The webCannot find module 'mermaid'typecheck error also reproduces onmainwithout this change; fix(web): main typecheck passes again after the Mermaid switch to pele #22570 and test(web): drop the Mermaid warmup that imports a removed package #22571 address it.Evidence
MP4s are real-time
simctl recordVideocaptures. GIFs are 8 fps derivatives, sped up as labelled. The long-press was sent as a pointer hold in the Simulator window, and the menu's Rename item was activated with an accessibility press. Thread data is synthetic.Rename thread: normal flow (iOS 26.5 Simulator)
The simulator did not reproduce the overflow reported from iOS 26 Nightly on a device. On a fresh presentation, base renders
Alert.promptwith the field inside the alert on both iOS 26.5 and iOS 27.0. On iOS 27.0 that also held at XXXL text size. These GIFs show the same flow on base and candidate: long-press, Rename, edit, confirm, title updated in the list. Candidate selects the current title on focus, so the full new title is typed instead of appended.Before (base fe414eb): native
Alert.prompt. No overflow on this simulator.After (candidate 8253ac3): the in-app prompt opens from the long-press context menu after the menu dismisses, and the confirmed title shows in the list.
Before recording · After recording
Rename thread: field overflows after a relayout (iOS 27.0 Simulator)
The same overflow shows on the simulator when the alert lays out again while it's open. In this run the Dynamic Type size changes to XXXL and back with the prompt open (
simctl ui content_size). This trigger is different from the reported one; the reported one didn't reproduce here.Before (base fe414eb): after the size change, the
UIAlertControllertext field shifts right and runs past the alert's trailing edge. It stays that way while typing and confirming.After (candidate 8253ac3): the same size change re-lays the in-app dialog, with stacked buttons at XXXL, and the field stays inside the card.
Field after the size change, full resolution:
Before recording · After recording
Link pull request over the Git sheet (candidate, iOS 26.5 Simulator)
From thread → Git → More, tapping Link pull request presents the prompt on top of the native form sheet. Typing
42works, and Cancel returns to the sheet. Nothing was linked.Recording
Written with Claude Opus 5.5 in Claude Code (T3 Code harness).
🤖 Generated with Claude Code