diff --git a/packages/junior-dashboard/e2e/conversations-mobile.spec.ts b/packages/junior-dashboard/e2e/conversations-mobile.spec.ts index 32fd694180..85c2214fcb 100644 --- a/packages/junior-dashboard/e2e/conversations-mobile.spec.ts +++ b/packages/junior-dashboard/e2e/conversations-mobile.spec.ts @@ -721,6 +721,27 @@ test("keeps the message in view while earlier history and late content load", as transcript.getByText("Transcript message 39 "), ).not.toBeInViewport(); + // Rows keep their real size while the reader scrolls up through them, so + // the transcript never corrects the reader's own scroll. On phones, such + // corrections make the transcript jump. + await transcript.evaluate((element) => { + const scrollTo = element.scrollTo.bind(element); + element.dataset.scrollCorrections = "0"; + element.scrollTo = (...args: Parameters) => { + element.dataset.scrollCorrections = String( + Number(element.dataset.scrollCorrections) + 1, + ); + scrollTo(...args); + }; + }); + await transcript.hover(); + for (let step = 0; step < 8; step += 1) { + await page.mouse.wheel(0, -150); + } + await expect(transcript.getByText("Transcript message 30 ")).toBeInViewport(); + await expect(transcript).toHaveAttribute("data-scroll-corrections", "0"); + await transcript.getByText("Transcript message 43 ").scrollIntoViewIfNeeded(); + // Content that grows above the reader, such as an image that loads late, // must not push the message they are reading out of view. await transcript.getByText("Transcript message 20 ").evaluate((element) => { diff --git a/packages/junior-dashboard/src/client/conversations/TranscriptRows.tsx b/packages/junior-dashboard/src/client/conversations/TranscriptRows.tsx index 2ca947768c..a0a683bb17 100644 --- a/packages/junior-dashboard/src/client/conversations/TranscriptRows.tsx +++ b/packages/junior-dashboard/src/client/conversations/TranscriptRows.tsx @@ -35,7 +35,14 @@ export function TranscriptUnreadMarker() { ); } -/** Leave room for control outlines inside the mobile row's paint bounds. */ +/** + * Lay out one transcript row at its real size. + * + * Rows do not use `content-visibility: auto`. A skipped row has an estimated + * size, and it changes size when the reader scrolls near it. Above the + * reader, each change needs a scroll correction while they scroll, and on + * phones those corrections make the transcript jump. + */ export function TranscriptRow(props: { /** Stable row id that holds the reader's place while layout changes. */ anchorKey?: string; @@ -46,7 +53,7 @@ export function TranscriptRow(props: { }) { return (
diff --git a/packages/junior-dashboard/src/tailwind.css b/packages/junior-dashboard/src/tailwind.css index 733b4bd9f1..c9875cf7c7 100644 --- a/packages/junior-dashboard/src/tailwind.css +++ b/packages/junior-dashboard/src/tailwind.css @@ -363,9 +363,4 @@ content-visibility: auto; contain-intrinsic-size: auto 3.5rem; } - - .mobile-transcript-row { - content-visibility: auto; - contain-intrinsic-size: auto 12rem; - } }