From e03e5bcdc988b5f5edfaaa3f938565784ad3740d Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Sun, 6 Sep 2026 16:56:08 +0800 Subject: [PATCH] fix(desktop): preserve glyphs at transcript clip edges Keep content-visibility paint containment for transcript boundaries while giving glyph ink a 2px overflow clip margin. This prevents Chromium from shaving flush-left assistant glyphs without changing the message box geometry. Extend the WideAssistantProse story contract to retain content visibility, the clip margin, and the existing full-width alignment. Fixes #4898 Generated-by: Codex --- apps/desktop/src/renderer/styles/chat-message.css | 6 ++++++ apps/desktop/stories/app-shell.stories.tsx | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/apps/desktop/src/renderer/styles/chat-message.css b/apps/desktop/src/renderer/styles/chat-message.css index c8c2074922..50c376205e 100644 --- a/apps/desktop/src/renderer/styles/chat-message.css +++ b/apps/desktop/src/renderer/styles/chat-message.css @@ -136,6 +136,12 @@ anchoring when a skipped block leaves and re-enters the viewport. */ .maka-chat-message-list [data-maka-transcript-boundary] { content-visibility: auto; + /* `content-visibility` supplies paint containment as well as skipping. + Assistant ghost bubbles are deliberately flush-left, and Chromium can + rasterize the first CJK glyph a fraction outside that content box; at a + zero-width clip edge it then shaves the glyph's leading stroke. Preserve + a tiny paint apron while keeping the boundary independently skippable. */ + overflow-clip-margin: 2px; /* First-paint intrinsic-size ESTIMATE for scroll-anchor stability, not a fixed height: `auto px` still grows to the block's real size after paint. 96px is the single-line answer baseline; tall multi-line blocks diff --git a/apps/desktop/stories/app-shell.stories.tsx b/apps/desktop/stories/app-shell.stories.tsx index 43ce44f709..f39dd02b14 100644 --- a/apps/desktop/stories/app-shell.stories.tsx +++ b/apps/desktop/stories/app-shell.stories.tsx @@ -964,9 +964,16 @@ export const WideAssistantProse: Story = { const paragraph = await within(answer).findByRole('paragraph'); const turn = paragraph.closest('.maka-turn'); if (!turn) throw new Error('Wide assistant paragraph did not render inside a turn'); + const boundary = paragraph.closest('[data-maka-transcript-boundary]'); + if (!boundary) throw new Error('Wide assistant paragraph has no paint-containment boundary'); const turnRect = turn.getBoundingClientRect(); expect(turnRect.width).toBeGreaterThan(680); expect(turnRect.right - paragraph.getBoundingClientRect().right).toBeLessThanOrEqual(1); + // `content-visibility: auto` implies paint containment. CJK glyph ink can + // extend a fraction past its line box, so a flush-left answer needs a + // small clip margin or Chromium shaves the first glyph on every line. + expect(getComputedStyle(boundary).contentVisibility).toBe('auto'); + expect(Number.parseFloat(getComputedStyle(boundary).overflowClipMargin)).toBeGreaterThanOrEqual(2); }, };