Skip to content

fix(ChatLayout): Safari reveals a document-scrolling composer - #10690

Draft
vjeux wants to merge 18 commits into
meta:mainfrom
vjeux:chat-layout-document-scroll-safari
Draft

vjeux wants to merge 18 commits into
meta:mainfrom
vjeux:chat-layout-document-scroll-safari

Conversation

@vjeux

@vjeux vjeux commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Review only this pull request's change: vjeux/astryx@0d75573...8e190c3

User impact

In Safari on iOS, tapping the composer of a ChatLayout whose scrollRef is the document puts it under the status bar.

Problem and solution fit

In a page that scrolls the document, Safari pans the visual viewport to the fixed dock when the keyboard opens, and keeps the pan. ChatLayout's lift adds to it. Firefox for Android pans at some shows only, so it needs that lift at the others.

Three narrower fixes failed on the Simulator. A lift less Safari's pan made Safari pan again at each change. Re-arming the put-back after ChatLayout's scroll left the pan in place. No lift with the tap claim kept left the composer under the keyboard: Safari then never panned.

Expected behavior and authority

spec:AST-099 FR3 puts a docked composer on the keyboard; FR4 keeps focus from panning the page. FR3 and FR4 now name two exceptions: Safari on iOS, and the shows before one leaves the composer covered elsewhere without the VirtualKeyboard API. Three Firefox rows and Gaps 16 and 17 cover them. They need the owners' stamp at this head.

Smallest restoration

Where scrollRef names the document's root or body, without the VirtualKeyboard API, shows leave focus to the browser until one finds the dock covered. The keyboard module's reveal-pan watch decides it, under a new opt-in dock option. The dock holds while the browser's reveal runs; a pan to the dock means no lift. A dock still covered after 0.7 s rises, and a clean show teaches the page to work as on main. After a touch or a wheel, the dock rises by the cover the pan leaves. Where the layout viewport follows the pan, as in Safari, it holds. Chrome and self-scroll mode are unchanged.

Evidence

Scope

  • One defect is restored.
  • Separable contradictory or unsettled tagalongs were removed or split.
  • No new public API, visual representation, default, or interaction model is hidden under the bug-fix label.
  • Public text and artifacts contain no internal Meta context.

Testing

  • useChatKeyboard.test.tsx and keyboardHeight.test.ts script time, touches and visual-viewport values:
    • No pan with a 290 px keyboard: no lift at 699 ms, then 290 at 700 ms after the report. The height reports of the keyboard's slide don't extend the wait. The next show lifts at once, with the focus takeover.
    • A pan decides only its own show. After a pan at 108 ms, the next show with no pan lifts at 700 ms and teaches the page. The show after lifts at once.
    • A drag unwinds Firefox's pan from 290 to 0: the dock's translate follows 90, 190 and 290, keeping the composer on the keyboard. Nothing is laid out and no scroll is read until the finger lifts; then the layout takes 290 once.
    • A fling that pans only the visual viewport is laid out once at its scroll end, with no lifted finger.
    • A slow drag of 0.3 px per report lays out nothing until the finger lifts, then once.
    • A composer show under a pinch zoom teaches nothing.
    • After a show learns the cover, a pan to the dock before any input goes back. The next show still lifts at once, with reduced motion too.
    • Safari's model, where innerHeight grows as the pan unwinds through a slow drag to the page's top: the lift stays 0, with no translate.
    • A caret reveal while typing, and a show for a field outside the composer, each have a case.
    • The tap claim, focus()'s reveal and the put-back each have a case before and after a page learns the dock is covered. Removing any one gate fails its case.
    • With the option off, the reveal-pan watch reports and listens as before; one visual-viewport read per report stays (INV11).
    • The cases fail on main. Chat, keyboard, utils and BottomSheet units: 2423/2423.
  • Safari on the iOS 26.2 Simulator, in scripted traces at 7297840 (browser and home-screen app): a tap, then drags with the keyboard up. The dock's applied lift is 0 px on every frame, and it never flips direction within 100 ms, as on 33bc644. Safari's own slide on a slow drag toward the top stays as in earlier releases (Gap 17, ChatLayout: in Safari on iOS, a slow scroll toward the top with the keyboard up slides the composer under the keyboard (document scroll) #10718).
  • In Firefox, while a scroll moves the pan after input, each report moves only the dock's translate. The layout takes the lift when the last finger lifts. After a fling, it takes it again when the fling comes to rest.
  • Firefox for Android in the emulator, at a64d445, with animations at normal scale, slow and removed:
    • Scroll, fling and scroll back with the keyboard up: the composer stays on the visual viewport's bottom, worst −0.5 px, as on main.
    • First show: covered 668 to 814 ms before the lift at normal scale, and 675 ms with animations removed (main: 0 ms). In two takes Firefox's own pan revealed it at 155 and 188 ms. Each is within Gap 16's wait, which ends at 3 s at most.
    • Second show: 0 ms at normal and slow scale, as on main. With animations removed, one of three takes was covered 599 ms. In that take, Firefox's own pan revealed the first show, so the page learned nothing. Its second show was the first the browser left covered, so the composer stayed covered until Gap 16's wait ended.
    • Frame times during the follow: p50 17 to 21 ms against main's 17 to 19 ms, with p95 and max overlapping. Chrome for Android, the control: p50 24 ms against main's 24.5 ms. No added long frames at any scale.
  • No keyboard: Chromium and WebKit's CI container, phone and desktop, read the same dock and message offsets on both builds. So does the Simulator.
  • The iOS home-screen app, on the Simulator, on a build of d051627: a tap, Done, Next from a probe field, and focus(). Each keyboard route rests the composer on the keyboard, and Done leaves no group. On main, a tap and Next put it off screen.
  • Core tsc, ESLint, check:knowledge and check:changesets pass.
  • The browser frames come from 8bb22d9 (banked on the fork) with chore(sandbox): a Chat Layout page with a case for each chat check #10672's page. A build of d051627 reads the same in Safari: 235 px in long, 199 px in composer.

Release check

  1. Red-first: the frames and unit cases above.
  2. feat(ChatLayout): the composer rides the software keyboard #8176 caused it. After a tap in long, the dock's top reads 235 px on 33bc644 (before feat(ChatLayout): the composer rides the software keyboard #8176) and on main with feat(ChatLayout): the composer rides the software keyboard #8176 reverted. It reads −102 px on 695653f (feat(ChatLayout): the composer rides the software keyboard #8176) and on the release candidate c99ad4a.
  3. Who sees it: every composer tap in a ChatLayout whose scrollRef is the document, in Safari on iOS.
  4. The cost is in Firefox for Android. A page's first show that leaves the composer covered keeps it so for about 0.7 s. That was 731 to 755 ms on a slow device at df30dc5, and 668 to 814 ms at a64d445. Later shows lift at once. Chrome never takes this path. The follow-up is ChatLayout: the first keyboard show covers a document-scrolling composer in Firefox for Android #10703.
  5. Safari on iOS keeps its own slide on a slow scroll toward the top, as in earlier releases (Gap 17, ChatLayout: in Safari on iOS, a slow scroll toward the top with the keyboard up slides the composer under the keyboard (document scroll) #10718). Chrome's intermittent late pan in the long case predates this change (ChatLayout: Chrome on Android sometimes pans the visual viewport after the lift, floating the composer above the keyboard (long case) #10713).

Writing rubric results

spec:AST-099 FR3, FR4, FR9's docked-container clause, the three Firefox rows, and Gaps 16 and 17:

  • R2: Gap 16 states measured values: Safari's pan on the Simulator (0 to 400 ms) and Firefox's slow-device cover (731 to 755 ms). Kept: Spec owners' ruling, 2026-11-08.
  • R4: Gaps 16 and 17 each give one line on the alternative not taken. They are a lift then a drop, and a lift that chases Safari's reveal. Kept: one line each, inside the gap.
  • R1, R3, R5, R6: none.

@vercel

vercel Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 9, 2026 2:54am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 8, 2026
@astracat-bot

astracat-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
🟡 Reviewed (for maintainers only) Nov 9, 2026, 3:05 AM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Nov 8, 2026
In a page that scrolls the document, Safari on iOS pans the visual
viewport to the fixed dock when the keyboard opens, and keeps the pan.
ChatLayout's lift added to that pan, so the composer went under the
status bar. Where no layout guide publishes the keyboard's slide,
ChatLayout now leaves the tap, the reveal and the dock's place to the
browser in that mode. With the VirtualKeyboard API, as in Chrome on
Android, and in self-scroll mode, nothing changes. AST-099 FR3 states
it.
@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Current run: The current CI run concluded skipped. Current analysis is unavailable.


Generated by PR Enrichment workflow | View current CI run

@vjeux
vjeux force-pushed the chat-layout-document-scroll-safari branch from b58dab0 to fa8cf7b Compare November 8, 2026 16:22
@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 8, 2026
@cixzhang

cixzhang commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

/approve-spec fa8cf7b

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 8, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested. The spec:AST-099 FR3 exception is approved at this head, so the direction is settled, and four fixes remain:

  • leavesRevealToBrowser and isKeyboardSurface test !isSelfScrolling, so a scrollRef on an inner scrolling element also loses the dock lift, the focus takeover and the composer group, while the approved FR3 text, the changeset, the docs and the JSDoc limit the change to a page that scrolls the document; gate on the document's scroller or widen the record and the evidence.
  • ChatLayout.doc.mjs still says every way into the composer focuses it without scrolling the page (line 9) and that Done rests focus on the composer group (line 138), which is false with scrollRef in Safari on iOS and Firefox for Android, and docsZh needs the same update.
  • Firefox for Android takes the new path unmeasured, yet the docs now say the browser reveals the composer there, and AST-099 makes Firefox for Android emulator evidence and iOS home-screen app evidence a merge gate, so add those results or limit the claim to Safari.
  • FR9's Docked containers clause and the FR3–FR4 verification row still require ChatLayout's dock to rise in Safari on iOS, so they need the same exception, followed by a new /approve-spec at the new head.

CI has not run on this head yet, because the pull request is a draft.

[Automated review]

vjeux added 2 commits November 8, 2026 08:49
The exception now applies only when scrollRef names the document's own
scroller: its root or its body. A scrollRef on an inner scrolling
element keeps the lift, the tap claim and the focus takeover. The docs
name the exception for Safari on iOS, in both languages. AST-099 FR9's
docked-container clause and the FR3-FR4 verification row name it too.
FR3 and FR9's docked-container clause now state the rule the code
keys on: ChatLayout's scrollRef names the document's scroller.
@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Nov 8, 2026
@cixzhang

cixzhang commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

/approve-spec b143b86

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 8, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested. The spec:AST-099 FR3 exception for a ChatLayout whose scrollRef names the document is approved at this head, and the gate now covers only the document's scroller, so the direction is settled. Three fixes remain:

  • Firefox for Android and the iOS home-screen app also lose the dock lift, the tap claim and the pan put-back through leavesRevealToBrowser, with no Firefox for Android emulator run or home-screen app run, which AST-099's Platform support makes part of the merge evidence, and ChatLayout.doc.mjs lines 9, 124 and 138 still promise Firefox for Android focus without page scroll and Done's park on the composer group.
  • The composer prop description (ChatLayout.doc.mjs:110) still says the wrapper is a group where Done rests focus, with no exception for a document scrollRef in Safari on iOS.
  • Miss: the browser-support guide (packages/cli/assets/docs/browser-support.doc.mjs:151) still says ChatLayout's composer leaves the page where it was and puts a Firefox pan back, which no longer holds with a document scrollRef.

The inner-scroller reach and the FR9 and verification-row wording from the last review are fixed. CI has not run on this head yet because the pull request is a draft.

[Automated review]

ChatLayout's docs, in English, Chinese and the dense line, and the
composer prop's description name the exception's real scope: a scrollRef
on the document in a browser without the VirtualKeyboard API, as Safari
on iOS and Firefox for Android. There ChatLayout leaves focus and the
reveal to the browser, with no composer group. The browser-support guide
names it beside the Firefox pan put-back.
@cixzhang

cixzhang commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 37f7a9b

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: the spec:AST-099 FR3 exception for a ChatLayout whose scrollRef names the document is approved at this head, and the docs now name every browser it reaches, so one fix remains:

  • Firefox for Android and the iOS home-screen app lose the dock lift, the tap claim and the pan put-back through leavesRevealToBrowser (useChatKeyboard.ts:526-528) with no Firefox for Android emulator run or home-screen app run, which AST-099's Platform support makes part of the merge evidence, while ChatLayout.doc.mjs and the browser-support guide now say Firefox for Android reveals the composer there, so please add those runs for a document-scrolling ChatLayout (tap, previous and next, focus(), Done).

The composer prop description, the Firefox sentences in the ChatLayout docs and the browser-support guide from the last review are fixed. CI has not run its build and test workflows on this head yet because the pull request is a draft.

[Automated review]

@cixzhang

cixzhang commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 386ebb1

@cixzhang

cixzhang commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

/approve-spec e1968f7

vjeux added a commit to vjeux/astryx that referenced this pull request Nov 8, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approval waits on an engineering owner's decision on the spec:AST-099 text at this head: this push rewrote FR3 (the dock now follows the cover the pan leaves after a touch or a wheel, and holds where the layout viewport follows the pan), FR9's docked clause and Gap 16, and added Gap 17 and a third Firefox for Android row, so an engineering owner records the decision by commenting /approve-spec <full head SHA>, which the author may do as an engineering owner.

Independent of that decision, these need fixing:

  • The follow mode recommits the dock's bottom and the transcript's padding, and reads scrollTop around those writes, on every visual-viewport report while the reader scrolls (useChatKeyboard.ts:364-371, :289, :425), which architecture:react-component-runtime INV18 and AST-099 FR3's "no per-frame layout work" do not allow, so follow the pan with the dock's compositor translate and commit the layout lift once the pan rests.
  • A composer show under a pinch zoom still teaches "covered" because the pan reads as null while the page is zoomed (keyboardHeight.ts:752), so in Safari on iOS one zoomed show brings back the stacked lift for every later tap on the page; follow the cover without learning when the pan is null, and add a zoomed case.
  • AST-099 Platform support makes Firefox for Android emulator evidence at the exact head merge evidence, and the description gives the 731–755 ms cover without its head and no result for the third Firefox row (spec.md:445), which checks the follow mode this push added.

The other-field learning, the watchWheels copy and the gate tests from the last review are fixed, and required CI has not run on this head because the pull request is a draft.

[Automated review]

While the dock follows the cover a pan leaves, each keyboard report
now moves only the dock's translate, from the keyboard module's
numbers, with no layout read or write. The layout takes the lift
once, when the reader's scroll comes to rest: at a lifted finger or
at the scroll's end, through the shared input stream.

A composer show under a pinch zoom, whose pan is the reader's, now
teaches nothing: its dock follows the cover instead.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 8, 2026
A fling that pans only the visual viewport raises no document scroll
end, so its followed lift waited for the next lifted finger. The
keyboard module now passes on the visual viewport's own scroll end
(subscribeViewportRest, one shared listener per window), and a
report that finds the pan unchanged also counts as rest.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 8, 2026
A report whose pan moved less than half a pixel counted as rest, so a
slow drag laid out the lift every few reports. Now only a report that
finds the pan exactly where it was, with no finger down, counts as
rest: the exact repeat that ends a fling's momentum. The hook keeps
the count of fingers down across its effect runs.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approval waits on an engineering owner's decision on the spec:AST-099 text at this head: since the last approved revision, FR3 changed again (the dock now follows the pan on its translate, and the layout takes the lift when the scroll rests), Gap 16 now says a pinch-zoomed show teaches nothing, and FR9's docked clause, Gap 17 and a third Firefox for Android row remain unapproved, so an engineering owner records the decision, including whether a dock moved by script on each visual-viewport report is acceptable, by commenting /approve-spec <full head SHA>, which the author may do as an engineering owner.

Independent of that decision, these need fixing:

  • The follow mode counts fingers down from its own touchstart, touchend and touchcancel subscriptions (useChatKeyboard.ts:432-445) beside the input stream's getDownPresses, so add a touch-based down count to the input stream and read it here, or say in the comment why getDownPresses, which drops a press at the scroll's pointercancel, cannot serve.
  • The Gap 17 hold is untested: switching off the layout-follows-pan check (keyboardHeight.ts:842) leaves every keyboard case green while the dock's translate climbs to −323 px in the Safari slow-scroll case (useChatKeyboard.test.tsx:866-920), so assert there that the dock's translate stays empty.
  • AST-099 Platform support makes Firefox for Android emulator evidence at the exact head merge evidence, and the description gives no emulator result at this head for the three Firefox rows (spec.md:444-446), including the translate follow this push changed.

The per-report layout commit and the pinch-zoom learning from the last review are fixed, and required CI has not run on this head because the pull request is a draft.

[Automated review]

The Safari slow-scroll case now asserts that the dock's translate
stays empty, so removing the hold fails it. A keyboard hide resets
the hook's finger count, so a lift the effect never heard cannot
keep a later fling from resting. The comment says why the input
stream's down presses cannot serve. FR3 says the layout takes the
lift when the last finger lifts, and again when a fling rests.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
FR3 now says plainly that the dock follows the pan on its compositor
translate, with no layout work at each change of the visual viewport.
It also says the layout takes the lift when the last finger lifts,
and again when a fling comes to rest. The hook's comment matches.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approval waits on an engineering owner's decision on the spec:AST-099 text at this head: since the last approved revision, FR3 changed again (the dock's follow is now stated as a compositor translate, and the layout takes the lift when the last finger lifts and again when a fling comes to rest), and FR9's docked clause, Gap 16, Gap 17 and the three Firefox for Android FR3–FR4 rows remain unapproved. An engineering owner records the decision, including whether a dock translate written by script on each visual-viewport report is acceptable, by commenting /approve-spec <full head SHA>; the author may do so as an engineering owner.

Independent of that decision, this needs fixing:

  • AST-099 Platform support makes Firefox for Android emulator evidence at the exact head merge evidence, and the description gives no emulator result at this head for the three Firefox rows (spec.md:446-448), including the translate follow.

The finger count's reason, the Gap 17 test and FR3's wording from the last review are fixed. Required CI has not run on this head because the pull request is a draft.

[Automated review]

@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

/approve-spec a64d445

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 9, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: the spec:AST-099 text at this head carries an engineering owner's approval, so the direction is settled and one piece of merge evidence remains.

  • AST-099's Platform support makes Firefox for Android emulator evidence at the exact head a merge gate, and the description gives no emulator result at this head for the three Firefox FR3–FR4 rows (docs/specs/AST-099-mobile-keyboard/spec.md:446-448); please run them with animations at normal scale and removed and a slow-device profile, and state the head and each row's composer bottom against the visual viewport's bottom.

Non-blocking: consider amending architecture:react-component-runtime INV11 so it names the dock's pan follow, and naming Gap 16's 3 s cap in the changeset. The earlier findings on learning from another field's show, the pinch-zoomed show, the finger count's reason and the Gap 17 test are fixed. Required CI has not run on this head because the pull request is a draft.

[Automated review]

vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
In the show that learned the browser leaves the dock covered, a pan
to the dock before any input dropped the lift and forgot what the
page learned, so the next show waited again. In Firefox for Android
under Remove animations a reveal can land after the lift. Now that
pan goes back, as at every later show, and the page keeps the cover.
The dock watch puts it back itself: the module's own put-back
measures from the opening report, before the lift moved the layout.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 9, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes requested: the spec:AST-099 text at this head is unchanged since an engineering owner approved it, so the direction is settled, and one piece of merge evidence remains.

  • AST-099's Platform support makes Firefox for Android emulator evidence at the exact head a merge gate, and the reported run is from the previous revision, before this push changed what Firefox's learning show does with animations removed (keyboardHeight.ts:883-887); please rerun the three Firefox FR3–FR4 rows (docs/specs/AST-099-mobile-keyboard/spec.md:446-448) at the final head with animations at normal scale and removed and a slow-device profile, and state the head and each row's composer bottom against the visual viewport's bottom.

The late-reveal fix itself is covered by two new cases that fail on the previous revision, and the earlier findings on the gate tests, the focus owner, the finger count's reason and the Gap 17 test are fixed. Non-blocking: consider amending architecture:react-component-runtime INV11 to name the dock's pan follow, naming Gap 16's 3 s cap in the changeset, and the comment wording suggested inline. Required CI has not run on this head because the pull request is a draft.

[Automated review]

| FR3–FR4 | ChatLayout's keyboard tests in jsdom and its interaction proofs in Chromium and WebKit | the fixed and the sticky dock with the keyboard shown and hidden; the message area's end padding; a transcript at its newest message; a page pinch-zoomed with the keyboard up; focus by tap, Tab, `focus()` and Done, under a finger and under a mouse | The dock left under the keyboard or lifted with none; the newest message unable to scroll above the composer; a transcript at its newest message left behind; the page panned to the composer's text under a finger; focus left in the text after Done, or the composer group focusable outside Done's park |
| FR3–FR4 | ChatLayout's keyboard tests in jsdom and its interaction proofs in Chromium and WebKit | the fixed and the sticky dock with the keyboard shown and hidden; the message area's end padding; a transcript at its newest message; a page pinch-zoomed with the keyboard up; focus by tap, Tab, `focus()` and Done, under a finger and under a mouse | The dock left under the keyboard or lifted with none; the newest message unable to scroll above the composer; a transcript at its newest message left behind; the page panned to the composer's text under a finger, outside FR3's document-scroll exception; focus left in the text after Done, or the composer group focusable outside Done's park |
| FR3–FR4 | Firefox for Android in the emulator, top-level document | ChatLayout whose `scrollRef` names the document, the page's first keyboard show: a tap on the composer, the keyboard shown | Once the wait ends (Gap 16), the composer does not rest on the keyboard: its bottom sits more than 0.5 CSS px below the visual viewport's bottom |
| FR3–FR4 | Firefox for Android in the emulator, top-level document | The same page's next keyboard show after one that left the composer covered: a tap on the composer, the keyboard shown | The composer does not rest on the keyboard at once: its bottom sits more than 0.5 CSS px below the visual viewport's bottom |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This push changes what this row measures with animations removed: the show that learns the cover now puts a late reveal pan back and keeps what it learned (keyboardHeight.ts:883-887). That is the case where the reported run, at the previous revision, left the second show covered 599 ms in one of three takes. Please rerun this row at the final head with animations at normal scale and removed and a slow-device profile, and state the composer bottom against the visual viewport's bottom.

Comment on lines +927 to +929
// Pans the visual viewport back to `top`, without scrolling the document. It
// scrolls `anchor` into view, or a probe fixed at `top` in the layout
// viewport, which the pan does not move.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking (INV29): the second sentence narrates the two branches. The reason is the quirk. Suggested:

// A fixed probe sits in the layout viewport, which the pan does not move.
// Scrolling it into view pans the visual viewport back.

This branch was successfully deployed

1 active deployment
Preview — 8e190c33 Deployed Nov 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants