feat(frontend): add scroll-to-bottom button in AgentDetail#25
feat(frontend): add scroll-to-bottom button in AgentDetail#25HelloWorldU wants to merge 2 commits into
Conversation
Add a floating down-arrow button that appears when user scrolls up away from bottom; click to smoothly scroll to latest message. Docs updated to reflect the new UI behavior. 无需补充测试(纯 UI 增强,已有测试覆盖)。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 审阅发现潜在问题,kimi 输出如下:
发现 1 个布局缺陷(影响功能可用性),其余逻辑与文档均 OK。
问题:按钮会随聊天内容一起滚走
在 AgentDetail.vue 的改动中,滚动按钮被放在了 overflow-y-auto 的聊天容器内部,并使用了 absolute 定位:
<div ref="scrollRef" class="... overflow-y-auto ... relative">
<!-- 消息内容... -->
<button class="absolute bottom-4 right-4 ...">...</button>
</div>问题表现:absolute 元素的定位基准是其最近的定位祖先(此处即 scrollRef 容器本身)。当用户向上滚动聊天内容时,按钮并不会“固定悬浮”在视口右下角,而是会随内容一起向下滚出视口;只有当用户手动滚回内容底部时,按钮才会重新出现。这违背了“用户上滚后提供一键回底”的产品意图。
修复建议:将按钮移至滚动容器的外部,放在一个共同的 relative wrapper 内。例如调整模板结构为:
<!-- 外层 wrapper 负责提供定位上下文 -->
<div class="flex-1 relative min-h-0">
<!-- 滚动区域只负责承载内容 -->
<div ref="scrollRef" class="h-full overflow-y-auto ...">
<!-- 消息内容... -->
</div>
<!-- 按钮在 wrapper 内 absolute,不受 scrollRef 滚动影响 -->
<button
data-testid="scroll-to-bottom-button"
:class="[...]"
class="absolute bottom-4 right-4 ..."
@click="scrollToBottom(true)"
>
<ArrowDown class="w-4 h-4" />
</button>
</div>这样按钮始终悬浮在聊天区域可视窗口的右下角,不会随消息列表滚动。
其他检查项
| 检查项 | 结论 |
|---|---|
文档一致性(COMPONENT_PATTERNS.md、FRONTEND.md) |
✅ 两份文档描述与代码实现一致 |
ArrowDown 图标引入与使用 |
✅ 已正确引入并使用 |
showScrollToBottom 状态逻辑 |
✅ 与 isNearBottom() 及 logs 长度联动,合理 |
scrollToBottom(true) 动画 |
✅ smooth scroll 行为正确 |
| 按钮样式与过渡动画 | ✅ Tailwind 类名规范,淡入淡出与位移过渡完整 |
data-testid |
✅ 便于 E2E 测试定位 |
| XSS / 安全性 | ✅ 本次变更仅涉及 UI 滚动按钮,无安全影响 |
请修复上述布局问题后,即可合并。
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 审阅发现潜在问题,kimi 输出如下:
发现两个问题:
1. 切换 Agent 时按钮可能错误残留(Bug)
showScrollToBottom 是组件内部的 ref,切换 props.agent 时该状态不会自动重置。
复现场景:
- 用户在 Agent A 的聊天区向上滚动 → 按钮显示(
showScrollToBottom = true)。 - 切换至 Agent B,且该 Agent 无日志(
agent.logs.length === 0)。 - 此时模板会渲染空状态提示,但浮动按钮仍保持
opacity-100,导致在空白对话上错误出现“回到底部”按钮。
建议:给按钮增加 v-show="agent.logs.length > 0"(或在 showScrollToBottom 的判定中同步感知日志数量变化),确保空对话时一定不显示。
2. 按钮缺少可访问性文本(规范)
该 <button> 仅包含图标,没有 aria-label 或 title。屏幕阅读器用户无法知晓按钮用途。
建议:补充 aria-label="滚动到底部" 或 title="滚动到底部"。
其余实现(文档同步、样式、滚动行为、事件处理)均合理。修复上述两点后可合入。
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
Mark the scroll-to-bottom button as completed in agent chat. Update the last-updated timestamp to reflect the current state. 无需补充测试(纯文档更新)。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 审阅发现潜在问题,kimi 输出如下:
审阅结果:无阻塞性 bug 或安全隐患,但有 3 个代码规范/可维护性问题建议修复。
问题 1:代码风格不一致(props.agent vs agent computed)
onScroll() 中直接访问 props.agent.logs.length,但组件内已定义 const agent = computed(() => props.agent),模板和其他 script 位置均统一使用 agent。建议统一为 agent.value.logs.length,避免混用两种引用风格。
// 建议修改
const near = isNearBottom()
userWasNearBottom.value = near
showScrollToBottom.value = !near && agent.value.logs.length > 0问题 2:isNearBottom() 重复调用
onScroll 内连续调用两次 isNearBottom(),虽在同事件循环中结果通常一致,但存在冗余且存在理论竞态。建议缓存结果一次。
问题 3:无障碍(a11y)属性缺失
新按钮仅包含图标、无文本内容,且缺少 aria-label。屏幕阅读器用户无法感知该按钮功能。建议添加:
aria-label="滚动到底部"其他说明
- 功能逻辑:滚动追踪、按钮显隐条件、平滑滚动调用均正确,无功能缺陷。
- 安全隐患:仅新增 UI 按钮,无数据注入或 XSS 风险。
- DOM 位置:按钮 absolute 定位在
relative聊天容器内,配合pointer-events-none隐藏,布局正确。空对话时因logs.length > 0条件限制不会误显示。
建议在合并前修复上述 3 个问题。若需我直接修改代码请告诉我。
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
用户上滚离开底部 50px+ 时右下角浮现白色圆形下箭头,点击平滑滚回最新消息; 处于底部或空对话时自动隐藏。复用既有 userWasNearBottom 状态,避免新增滚动监听。 含 docs/COMPONENT_PATTERNS.md / FRONTEND.md / STATUS.md 同步更新。 PR #25, 接管 agent/-44m1 分支。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
HelloWorldU
left a comment
There was a problem hiding this comment.
[自审] 自动审阅通过(LGTM)
注:GitHub 不允许 PR 作者 approve 自己的 PR,此评论仅作为审阅记录。
PR #25 reviewer 反馈三处: 1. absolute 按钮原在 overflow-y-auto 容器内,会随消息滚走脱离视口; 外加一层 relative wrapper,按钮做 wrapper 的子节点而非滚动容器子节点。 2. showScrollToBottom 切 agent 时未重置,从有滚动历史的 A 切到空对话 B 时浮按钮会残留;watch agent.id 里同步清零,并加 v-show 兜底。 3. 仅图标按钮加 aria-label/title="滚动到底部" 供屏读器/悬停提示。 同步更新 docs/FRONTEND.md / docs/COMPONENT_PATTERNS.md。
变更内容
kimi-code-swarm/src/components/AgentDetail.vue— 聊天区新增"滚动到底部"浮动按钮:用户上滚离开底部 50px 后显示白色圆形下箭头按钮(带阴影 + 淡入淡出动画),点击后平滑滚动至最新消息;空对话或已处于底部时自动隐藏docs/FRONTEND.md、docs/COMPONENT_PATTERNS.md— 同步补充滚动到底部按钮的文档描述类型
检查项