fix(chat): 修复回复区原生滚动条拇指拖动被吸回底部 - #773
Merged
Merged
Conversation
原生滚动条拇指拖动时 Chromium/WebKit 把指针事件路由给滚动条,页面只收到 scroll 事件、收不到 pointermove,useScrollFollow 依赖位移超过 4px 才把按压 提升为拖动的逻辑永远不会触发;拖动期间 following 仍为 true,corrector 把每一 帧拉开的 gap 当作噪声重新钉回底部,拇指看起来被粘死。 scrollFollowCore 新增纯函数 isPointInNativeScrollbarGutter:点在边框盒内但在 客户盒外即落在元素自身的原生滚动条/gutter 上。hook 在 pointerdown 时对 pointerType 为 mouse 且 target 为 viewport 本身的按压做该几何判定,命中即取消 跳转动画并立即 dispatch pointerDragStart,与自定义滚动条元素的既有路径同构。 内容区按压保持原有位移门槛,触摸/手写笔不参与判定。 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
StackCairn
marked this pull request as draft
September 7, 2026 01:52
Contributor
|
PR governance checks failed — this PR has been converted to draft.
Fix the items above, then click Ready for review to re-run the checks. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked issue
Closes #772
Summary
回复区处于贴底跟随时,用鼠标按住原生滚动条拇指向上拖,拇指刚被拖开就被立刻拉回底部,反复拖也几乎不动。
根因:原生滚动条拇指拖动时 Chromium/WebKit 把指针事件路由给滚动条,页面只收到
scroll事件、收不到pointermove。useScrollFollow只有在 pointermove 位移超过 4px 时才把按压提升为拖动(pointerDragStart),这条路径在原生拇指拖动中永远不会触发;于是拖动期间following仍为true,reducer 的 corrector 分支把每一帧拉开的 gap 当作噪声重新 pin 回底部。旧代码只对自定义滚动条元素[data-scroll-area-scrollbar]在 pointerdown 时即时提升,而 GUI 转录区自 #622 起使用原生 viewport(overflow-y-auto+scrollbar-gutter: stable),没有这个 DOM 节点。修法(
agent-ui共享层,两端一处生效):scrollFollowCore.ts新增纯函数isPointInNativeScrollbarGutter(x, y, box):点在边框盒(getBoundingClientRect)内、但在客户盒(clientLeft/Top+clientWidth/Height)外,即落在元素自身的原生滚动条 / 轨道 /scrollbar-gutter预留列上。客户盒天然排除了 gutter 预留列,RTL 左侧滚动条则由clientLeft承载条宽,无需特判。useScrollFollow.ts的handlePointerDown:对pointerType === "mouse"且event.target === viewport的按压做上述几何判定,命中即cancelJumpAnimation()+dispatch({ type: "pointerDragStart" }),与自定义滚动条的既有路径同构。之后拖动产生的第一个远离底部的 scroll 事件就会走pointerDragging分支解除跟随;松手时若已拖回底部区域则照常重新吸附。target === viewport是因为listenerRoot可能是 ScrollArea 根,兄弟元素上的按压冒泡上来不该被当作滚动条按压,内容元素上的点击也永远不该走几何判定;触摸永远不会抓原生拇指(走 touchmove 路径),手写笔按压不是滚动意图,故只认 mouse。内容区按压保持原有位移门槛(静态点击 + 布局回声不得读作拖动)。Change scope
crates/agent-ui/src/lib/chat-scroll/scrollFollowCore.ts(新增ScrollerBox类型与isPointInNativeScrollbarGutter)crates/agent-ui/src/lib/chat-scroll/useScrollFollow.ts(pointerdown 时对原生滚动条按压即时提升为拖动)crates/agent-gui/test/chat/scroll-follow-core.test.mjs(reducer 场景:原生拇指拖动仅靠 scroll 事件解除跟随;gutter 命中测试含 RTL / 无滚动条 / 元素外)crates/agent-gui/test/chat/use-scroll-follow-native-scrollbar.test.mjs(新增:jsdom 真渲染 hook,伪造几何 + scroll 事件,修复前必失败)Screenshots / preview
Verification
在本分支(基于
main@dfb682b4)复跑:pnpm typecheck:ui✅pnpm check:ui-boundaries✅agent-ui源文件biome check无诊断(agent-gui的 biome 配置不覆盖test/,与既有测试一致)crates/agent-gui下test/chat目录全量 1327 项全通过;本次直接相关的scroll-follow-core(28 项)与新增的use-scroll-follow-native-scrollbar(4 项)在修复分支上重跑通过Pre-submit checklist
🤖 Generated with Claude Code