Uh oh!
There was an error while loading. Please reload this page.
fix(ui): restore usable scrolling for one-line code blocks - #3170
Conversation
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
💤 Files with no reviewable changes (1)
Included review availability: Your plan provides up to 3 included reviews per hour; 2 remain after this review. 📝 WalkthroughProblem solvedThis PR restores horizontal scrolling for one-line Markdown code blocks. It moves the copy action into a dedicated Source of truthThe PR extends the existing Markdown code-block renderer and message-selection logic. It does not create a parallel rendering path. The Solution size and complexityThe changes form the smallest coherent solution shown by the supplied summary:
The toolbar, layout state, selection exception, and scrollbar behavior address separate regression causes. No implementation or test change can be deleted without weakening behavior or regression coverage based on the supplied diff. Complexity delta
Maintenance complexity increases in the affected UI path. The increase is justified by the separate copy-button, scrollbar, layout, and pointer-capture requirements. Optional review findings remain follow-up considerations. They are not implementation requirements for this PR. ValidationThe PR reports a rebuild, 182 passing UI tests, linting, and one passing Electron code-scroll test. The review reports green CI and a PASS result with no P0, P1, or P2 issues. A follow-up commit removes a stale scrollbar implementation assertion from the UI tests. A P3 review request asks for before-and-after screenshots in light and dark themes. Required-check status is unverified here because no direct check output is available. Review-relevant risks
No security, licensing, release, or governance effect was identified in the current diff. The person performing the merge reviews the final diff. A maintainer makes the final determination. WalkthroughMarkdown code blocks now classify single-line and multiline layouts, support horizontal scrolling, preserve native selection scrolling, and expose localized collapsible controls for plaintext blocks. Unit and Playwright tests cover layout, accessibility, wheel, keyboard, and drag interactions. ChangesCode block scrolling
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk:🔵 Low · up to The PR is mergeable with owner awareness of a bounded dependency-notice mismatch: the permitted version range may include versions not covered by the exact-version MIT notice override; no other actionable merge blocker is supplied. Sequence Diagram(s)sequenceDiagram
participant MarkdownBody
participant CodeBlockViewport
participant useMessageSelectionQuote
participant User
MarkdownBody->>CodeBlockViewport: render classified code block
User->>CodeBlockViewport: scroll with wheel or keyboard
User->>useMessageSelectionQuote: start pointer selection
useMessageSelectionQuote->>CodeBlockViewport: detect native selection-scroll region
useMessageSelectionQuote-->>User: skip pointer capture
User->>CodeBlockViewport: drag-select and horizontally scroll
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR Summary by QodoRestore horizontal scrolling for single-line Markdown code blocks
AI Description
Diagram
High-Level Assessment
Files changed (10) |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/ui/src/markdown-body.tsx (1)
20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove the unnecessary
ClickScrollPlugin.
clickScroll: 'instant'does not require this plugin. Remove its import and global registration to reduce bundle size and initialization work.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a1c5e907-e619-455e-a0db-6127feace5d0
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (9)
apps/desktop/e2e/code-scroll.spec.tsapps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txtpackages/ui/package.jsonpackages/ui/src/__tests__/markdown-body.test.tspackages/ui/src/__tests__/message-selection-quote-boundary.test.tspackages/ui/src/markdown-body.tsxpackages/ui/src/styles.csspackages/ui/src/use-message-selection-quote.tsscripts/generate-third-party-notices.mjs
Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.
Uh oh!
There was an error while loading. Please reload this page.
Code Review by Qodo
1. |
Uh oh!
There was an error while loading. Please reload this page.
Astro-Han
commented
Aug 18, 2026
Thanks for the fix — the broken scrolling is real and the diagnosis is precise (the absolute-positioned copy button covers the top-right of untitled code blocks, the turn-level Conclusion: PASS — no P0/P1/P2. P3-1 (merge gate): the PR has no before/after screenshots. This visually changes every code block (plain-text blocks gain a 32px bordered toolbar, single-line blocks grow to ~72px, language-block content shifts down as the Astryx P3 (optional): AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on 中文摘要(AI 辅助审查)结论:PASS(无 P0/P1/P2)。问题三源精确定位:绝对定位复制按钮盖住无标题块右上角 + turn 级 setPointerCapture 吞掉滚动条拖拽/跨边缘选区 autoscroll + macOS 隐藏 overlay scrollbar 使长行不可达;修复各就各位(工具栏化+指针豁免+OverlayScrollbars custom-elements 模式保留原生 viewport 保选区/键盘滚动),e2e 直接验证四个曾被破坏的交互(滚动条拖拽/轨道点击/键盘/选区 autoscroll),主题映射/垂直滚不被吞/quote-from-code 存活均已核对。CI 全绿。P3-1(合并 gate):无 before/after 截图——本 PR 视觉上改变每个代码块(纯文本块新增 32px 带边框工具栏、单行块增高至 ~72px、语言块内容因中和 Astryx -spacing-2 上拉而下移、长行新增持久滚动条),按仓库规则需要 light/dark 前后截图。P3(可选):title="" 使纯文本块首次拥有 header,配合恒传 isCollapsible 使 ≥10 行纯文本块可变折叠——新交互 PR 未提及,需确认是有意;滚动条 slot 覆盖底部 10px 条带(z-index:1),该处 pointerdown 触发 clickScroll 而非文本选区/复制——建议用 CJK 长命令截图核实;OverlayScrollbars(~30KB)换持久主题滚动条+触控拖拽是可选产品决策但 PR 未陈述取舍;e2e 未验证嵌套滚动核心承诺(悬停代码块不破坏外层 chat 垂直滚动)与工具栏复制按钮可点;markdown-body.tsx 自定义 ArrowLeft/Right handler 与 tabIndex=0 viewport 的原生键盘滚动冗余且无条件 preventDefault(含提示词选区折叠+滚动),建议删除或仅在仍有滚动余量时拦截。 |
Astro-Han
left a comment
There was a problem hiding this comment.
The scrolling solution is well targeted: it preserves Astryx's native focusable viewport, isolates OverlayScrollbars to one-line blocks, and covers pointer, keyboard, selection, thumb, and track paths without building a parallel code-block component. Two boundary details remain.
From first principles, a control needs a name and a shipped dependency needs a stable reviewed license identity. For headerless plaintext, either do not expose collapse or provide a localized accessible name; for OverlayScrollbars, make the version/notice contract explicit rather than combining a moving caret range with an exact-version override.
Review performed with two Codex reviewer agents and DeepSeek V4 Flash as advisory tools; I verified the findings against the latest head and live green CI.
中文评论
滚动方案很克制:保留 Astryx 原生可聚焦 viewport,只对单行 block 隔离使用 OverlayScrollbars,并覆盖 pointer、keyboard、selection、thumb 和 track 路径,没有新建并行 code-block 组件。仍有两个边界问题。
从第一性原理看,control 必须有名称,发布依赖必须有稳定、已审查的 license identity。对无 header 的 plaintext,要么不暴露 collapse,要么提供本地化 accessible name;对 OverlayScrollbars,应显式固定 version/notice 契约,而不是把移动的 caret range 与精确版本 override 组合。
本次审查使用了两位 Codex reviewer agents 与 DeepSeek V4 Flash 作为辅助工具;我已依据最新 head 和实时绿色 CI 复核问题。
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
18261a0 to
0486a93CompareGenerated-by: Codex
0486a93 to
d9898b8Compare
Astro-Han
left a comment
There was a problem hiding this comment.
The move back to native scrolling removes the earlier dependency/license drift, and polling is better than the fixed geometry timeout. The latest required E2E still fails because the new vertical-centering assertion measures glyph ink bounds rather than the layout box it intends to constrain.
Following Occam's razor, delete this low-quality metric or replace it with the actual line wrapper/viewport layout box after visual verification; changing production spacing to satisfy font ascent/descent asymmetry would optimize for the test rather than the user-visible requirement. The existing accessible-name finding on plaintext collapse is already public, so I am not duplicating it here.
Reviewed with Codex using two independent review passes and DeepSeek V4 Flash as an external adversarial pass; I verified the metric and live E2E failure against this exact head.
中文
回退到原生滚动已消除之前的依赖/许可证漂移,polling 也优于固定等待。但最新 required E2E 仍失败,因为新的垂直居中断言测量的是 glyph ink bounds,而不是它真正想约束的 layout box。
按奥卡姆剃刀,应删除这个低质量指标,或经视觉核验后改测真实 line wrapper/viewport box;不要为了字体 ascent/descent 不对称去修改生产布局。plaintext collapse 的 accessible name 问题已有公开评论,这里不重复。
本次由 Codex 两轮独立审查,并使用 DeepSeek V4 Flash 做外部对抗审查;我核对了当前 head 和 E2E 失败。
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Actionable comments posted: 1
🔇 Additional comments (3)
packages/ui/src/markdown-body.tsx (2)
38-38: LGTM!Also applies to: 191-210
179-179: 🩺 Stability & Availability
⚠️ Unverified finding
Sandbox verification was unavailable.Verify the new locale-provider requirement.
useUiLocale()now runs for everyMarkdownCode, before the Mermaid early return. The hook throws whenMarkdownBodyrenders outsideLocaleProvider. This can make Mermaid and standalone Markdown consumers fail at runtime.Confirm that every
MarkdownBodycaller and test is insideLocaleProvider. If not, reuse the closest existing provider boundary before adding fallback state.Disposition: follow-up.
As per path instructions: report only concrete, reproducible risks and reuse the closest existing seam before adding new behavior.
packages/ui/src/__tests__/markdown-body.test.ts (1)
48-60: LGTM!
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a63974d9-717e-4632-bfce-0837d773c767
📒 Files selected for processing (2)
packages/ui/src/__tests__/markdown-body.test.tspackages/ui/src/markdown-body.tsx
Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.
Uh oh!
There was an error while loading. Please reload this page.
Astro-Han
left a comment
There was a problem hiding this comment.
The production scrolling seam is mostly right: Astryx keeps ownership of the native viewport, and the pointer-capture exception is narrowly scoped. The current head is not ready because its new required E2E asserts font glyph-ink symmetry rather than the layout box the CSS centers, and that exact assertion is failing on Linux CI. I also found a public-component compatibility regression from making useUiLocale() unconditional for every code block.
AI-assisted review: Codex coordinated two independent reviewer passes and an OpenCode Go DeepSeek V4 Flash high-effort adversarial pass. I verified exact head 15e89b85f99ddd27f3d3477cf2e2098ad2d4d1e4, Astryx/CSS ownership, the public export and locale hook, and the failing required E2E. No local tests were run.
中文审查
生产滚动 seam 基本正确:原生 viewport 仍由 Astryx 管理,pointer-capture 豁免范围也足够窄。当前不能合并,因为新增 required E2E 测量的是字体 glyph ink 对称性,不是 CSS 居中的 layout box;该断言正在 Linux CI 失败。另外,所有代码块无条件调用 useUiLocale(),给公共组件新增了未声明的 Provider 硬依赖。
本次为 AI 辅助审查,已核验精确 head、Astryx/CSS 责任边界、公共导出、locale hook 和失败的 required E2E;未运行本地测试。
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Astro-Han
left a comment
There was a problem hiding this comment.
This is now a focused fix at the existing Astryx seam: the copy control remains in the native CodeBlock toolbar, the one-line body keeps the native horizontal viewport and keyboard/selection behavior, and only pointer gestures originating inside that viewport bypass Turn-level pointer capture. The locale/provider and layout-metric regressions from earlier heads are resolved.
I found no reproducible correctness issue on this head. All current required checks are green. The inline P3 is only an Occam cleanup and does not block approval.
AI-assisted review disclosure: Codex performed the final review using two independent reviewer passes and OpenCode Go DeepSeek V4 Flash (high effort) as an adversarial advisory pass. I verified the Astryx DOM seam, selection/scroll boundary, accessibility name, exact head dce234bd0, and live CI.
中文评论
当前实现已经收敛到 Astryx 的既有扩展点:copy control 留在原生 CodeBlock toolbar;单行代码继续使用原生横向 viewport、键盘和文本选择;只有从该 viewport 发起的 pointer gesture 才跳过 Turn 层 pointer capture。此前 head 的 locale/provider 与布局度量问题都已解决。
当前 head 未发现可复现的正确性问题,所有必需检查均已通过。行内 P3 仅是奥卡姆剃刀式清理,不阻塞 approve。
AI 辅助审查说明:Codex 使用两轮独立 reviewer 审查,并以 OpenCode Go DeepSeek V4 Flash(high effort)进行对抗性辅助审查;我已核对 Astryx DOM seam、selection/scroll 边界、无障碍名称、精确 head dce234bd0 与实时 CI。
Uh oh!
There was an error while loading. Please reload this page.
jackwener
commented
Aug 19, 2026
Refreshed this branch onto current The product change is unchanged. The only review follow-up is the approved P3 cleanup: I removed the two negative assertions coupled to the abandoned Fresh verification on this exact head:
@Astro-Han, please re-review the refreshed exact head so the independent human-review gate can close. |
Astro-Han
left a comment
There was a problem hiding this comment.
The refreshed head 46a36de preserves the previously reviewed production behavior and applies only the agreed Occam cleanup: the two assertions coupled to the abandoned scrollbar implementation name are removed. I rechecked the exact delta from the approved head, the current PR diff, prior findings, and live required checks. The accessibility, standalone-provider, layout-metric, native-scroll, pointer-selection, and deterministic-E2E boundaries remain resolved.
AI-assisted review disclosure: Codex verified the refreshed exact head and current GitHub state; the human maintainer reviewed the final result and authorized approval and merge.
中文评论
刷新后的 46a36de 保留了此前已审查的生产行为,只执行了已同意的奥卡姆剃刀式清理:删除两条与废弃 scrollbar 实现名耦合的断言。我重新核对了相对已批准 head 的精确变化、当前 PR diff、既有 findings 和实时 required checks。无障碍名称、standalone provider、布局度量、原生滚动、pointer selection 与确定性 E2E 边界仍然全部解决。
AI 辅助审查说明:Codex 核验了刷新后的精确 head 和当前 GitHub 状态;人工维护者审阅最终结果并明确授权 approve 与 merge。
Uh oh!
There was an error while loading. Please reload this page.
Summary
Verification
npm run rebuildnpm --workspace @maka/ui test— 182 passednpm run lint -- --diagnostic-level=errornpm --workspace @maka/desktop run e2e -- e2e/code-scroll.spec.ts— 1 passedorigin/mainbehavior with this branch in the desktop GUIRoot cause
Astryx places the copy button absolutely when a plaintext CodeBlock has no header, so the control can cover the end of a long one-line value. Independently, Maka captures pointer gestures on the enclosing Turn for quote selection; that retargets pointer movement away from the nested code viewport and prevents Chromium from continuing native scrollbar or edge-selection scrolling. The fix gives CodeBlock a structural toolbar and lets its native viewport retain ownership of scrolling and selection gestures.
AI use
Select exactly one:
Tool(s) and scope: OpenAI Codex assisted with root-cause analysis, implementation, regression tests, rebase, and local verification. The contributor reviewed the resulting changes.
Checklist
Does this PR entail a change in behavior?