Skip to content

fix(messages): hide pointer-triggered focus ring#338

Open
youxikexue wants to merge 1 commit into
xintaofei:mainfrom
youxikexue:fix/conversation-pointer-focus-ring
Open

fix(messages): hide pointer-triggered focus ring#338
youxikexue wants to merge 1 commit into
xintaofei:mainfrom
youxikexue:fix/conversation-pointer-focus-ring

Conversation

@youxikexue

Copy link
Copy Markdown
Contributor

问题

在 Windows 桌面版或通过分享链接打开的网页端中,Agent 输出内容后,点击消息文本或正文空白处,整个消息滚动区域会出现焦点边框,边框包含右侧滚动条;点击区域外后消失。

复现步骤:

  1. 打开一个已有 Agent 输出内容的对话;
  2. 点击消息文本或正文空白处,不点击链接、按钮或输入框;
  3. 消息滚动区域四周出现完整焦点边框。

预期行为:鼠标点击正文后不显示键盘焦点提示,但仍可使用方向键、PageUp/PageDown 等按键滚动消息。通过 Tab 键进入消息区域时,应继续显示焦点提示。

原因

VirtualizedMessageThread 为支持键盘滚动,给消息滚动视口设置了 tabIndex=0,并在点击非交互正文时调用 focus();视口同时使用 focus-visible:ring-2 提供键盘焦点提示。

Chromium/WebView 会将鼠标事件中调用的程序化 focus() 判定为 :focus-visible,因此鼠标点击也触发了原本用于键盘导航的焦点环。相关行为由提交 259989f 引入。

方案选择

考虑过以下方式:

  1. 删除焦点环:会同时删除 Tab 导航所需的焦点提示;
  2. 删除 tabIndex 或点击聚焦:会破坏现有键盘滚动;
  3. 仅区分本次焦点是否来自鼠标:保留现有交互,只抑制鼠标点击产生的错误焦点环。

本 PR 采用方案 3,保留原有键盘操作和无障碍设计,只修正不同输入方式下的视觉反馈。

改动

  • 左键点击非交互正文并调用 focus() 前,为消息视口写入临时的鼠标焦点来源标记;
  • 鼠标来源且命中 :focus-visible 时,通过局部样式隐藏焦点环;
  • 视口失焦或组件卸载时清理标记;
  • 保留现有 tabIndex、点击聚焦、交互元素过滤、右键处理和键盘焦点样式。

改动仅涉及 VirtualizedMessageThread 及对应回归测试,不修改全局 ScrollArea 或基础焦点样式。

影响评估

  • 保留 Tab 焦点提示、键盘滚动及链接、按钮、文本选择和右键等原有交互;
  • 改动仅作用于消息视口的临时 DOM 状态和局部样式,不涉及数据、文件保存、后端或其他滚动区域;桌面端和网页端共用该逻辑;
  • 鼠标点击后到视口失焦前,键盘滚动也不显示焦点环;通过键盘重新聚焦后恢复。这是本方案的明确取舍。

验证

  • 4 项定向回归测试、ESLint、完整 Vitest(182 个测试文件、2288 项测试)、Next.js 构建和 git diff --check 均通过;
  • Windows Tauri 开发版已实机验证,原焦点边框问题未再复现;网页端人工验收待记录。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant