## 来源 2026-07-28 对 `b1630e5^...HEAD` 的 Standards review。相关重构:#236。 ## 问题 `SkillPreloadSection.tsx` 将候选列表实现为手写绝对定位浮层,每个候选项使用: ```tsx <div role="button" onClick={...}> ``` 但没有 `tabIndex`、键盘事件、Escape 关闭、焦点进入/返回或浮层碰撞管理。结果是鼠标用户可以添加/移除预载 Skill,键盘用户无法可靠聚焦和选择候选项。 这违反 `DESIGN.md`: - Select / Combobox / Menu 使用 Radix 或现有可访问原语; - 禁止裸 `div onClick`; - Menu / Popover 正确管理 focus、Escape 和焦点返回。 该行为在 #236 前已存在,但拆分后的新组件继续固化了问题,因此单独修复,不混入纯重构票。 ## 目标行为 - 触发按钮可用 Enter/Space 打开选择器。 - 打开后焦点进入搜索框或首个候选项。 - 候选项使用语义化 button、checkbox item 或现有可访问组件,不使用裸 `div onClick`。 - Enter/Space 切换选中状态;屏幕阅读器能感知名称和 checked/selected 状态。 - Escape 关闭最上层浮层并把焦点还给触发按钮。 - 点击外部关闭;关闭时沿用现有逻辑清空搜索词。 - 浮层进行窗口碰撞处理,不因靠近边缘而越界。 - 鼠标多选、搜索、已选列表删除和保存 payload 行为不变。 ## 实现约束 - 优先复用 `src/renderer/src/components/ui/` 中现有 Radix 封装;若现有 primitive 组合足够,不新增组件库。 - 保持 `SkillPreloadSection` props 与 `AgentEditDialog` 保存契约不变。 - 保持现有设计 token、密度和视觉层级;不引入新颜色、阴影体系或装饰性动画。 - 搜索输入和候选项必须有可访问名称;Tooltip 不作为唯一 label。 ## 测试 使用 Testing Library 按用户行为验证: 1. 键盘打开并聚焦搜索/候选区域; 2. Enter/Space 选择和取消一个 Skill; 3. 选中状态可通过 role + checked/selected 查询; 4. Escape 关闭并恢复触发器焦点; 5. 点击外部关闭并清空搜索; 6. 搜索过滤与无结果状态; 7. 鼠标点击和最终保存 payload 不回归。 不要依赖内部 DOM 层级或 CSS selector。 ## 验收标准 - [ ] 候选列表无裸 `div role="button"`。 - [ ] 全流程可仅用键盘完成。 - [ ] Escape、焦点进入与焦点返回符合 DESIGN.md。 - [ ] 现有 AgentEditDialog 行为与 props 不变。 - [ ] 相关 renderer 测试、`pnpm run typecheck`、`pnpm run build` 通过。 ## 非目标 - 不重新设计 AgentEditDialog 信息架构。 - 不修改 Skill preload 的领域规则或持久化格式。 - 不调整 MCP、Tool Scope 等其他字段分组。
Activity
suntianc commentedon Jul 29, 2026
已在 #245 完成实现并推送;Ubuntu、macOS、Windows CI 均通过。