十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DeepSeek Harness 悬停卡片一键复制:HoverCard copyText 交互契约与实现解析

DeepSeek Harness 悬停卡片一键复制:HoverCard copyText 交互契约与实现解析 人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载悬停卡片HoverCard是 DeepSeek Harness Web 客户端中 Workspace 浏览器行Workspace 目录、Session 标题的预览机制。本篇技术指南以项目归档的设计笔记 .agents/notes/archived/feature/2026-07-31-hover-card-click-copy.md 为核心讲解 HoverCard 如何通过copyText/copyLabel/copiedLabel三个可选属性实现点击卡片即复制主值涵盖指针激活与文本选择的优先级契约、共享剪贴板助手的回退策略、一秒成功反馈的几何保持以及 Workspace 浏览器侧的载荷决策规则。读完本文你将掌握该原子组件的完整交互契约、两处真实消费者Workspace 卡与 Session 卡的接入方式以及驱动这些行为的源码与测试证据。问题背景悬停卡暴露的值无法高效复制Workspace 浏览器中的两类行——Workspace 行与 Session 行——在视觉上会裁剪它们在悬停卡片中完整暴露的两个值Workspace 目录路径与Session 标题。行内文本超出可用宽度时被截断而悬停卡虽然完整展示这两个值但此前只能依赖手动框选文本再复制悬停卡本身允许文本选择由前一期的指针宽限修复保证见 .agents/notes/archived/bug-fix/2026-07-30-hover-popup-pointer-grace.md但选中一个已知的单个值是精度要求过高的手势——需要精准框选整个路径或标题且卡片没有任何反馈告知用户剪贴板是否真的接受了写入。设计决策让整张卡片成为复制按钮设计笔记中的核心决策是由HoverCard原子组件承担激活即复制的交互面而不是由两个消费者各自实现。具体而言组件接受三个可选/必需属性属性类型作用copyTextstring \| undefined可选。激活时要复制的主值传入后卡片整体获得按钮语义同时该值会拼入卡片的可访问名称accessible namecopyLabelstring必需。本地化的激活标签前缀例如Copy/复制用于拼接可访问名称Copy: /full/pathcopiedLabelstring必需。本地化的成功可见标签例如Copied/已复制在复制成功后替换卡片内容展示当copyText存在时源码中的copyable copyText ! undefined见 HoverCard.tsx整张卡片获得指针与键盘双通道的按钮语义rolebutton、tabIndex{0}、cursor: pointer键盘焦点可见:focus-visible描边卡片的可访问名称由本地化动作前缀 精确值构成例如Copy: /full/path辅助技术用户与鼠标用户获得一致的信息点击或按Enter/Space时通过共享剪贴板助手写入copyText中的精确值只有当宿主导航器host确认接受了写入卡片内容才会在最多一秒内替换为成功标签成功标签的反馈保持复制前的卡片高度并在卡片关闭时清除。当未传入copyText时卡片保持原有的只读/可选中行为不获得任何按钮语义。载荷由消费者决定而非原语推断设计笔记强调一个边界复制什么由 Workspace 浏览器决定而不是让原语从渲染文本中推断。原因在于悬停卡内容并非只有主值一种信息——Workspace 卡还包含创建时间Session 卡还包含相对时间与运行状态若直接复制卡片的textContent会把主值与时间、状态文本拼接导致剪贴板载荷依赖呈现方式与本地化文案。因此Workspace 卡传入完整目录路径copyText{row.cwd}非空白的 Session 卡传入完整显示标题copyText{row.blank ? undefined : row.title}空白的新建 Session 卡保持只读其本地化标签如New Session/新会话只是占位文案不是会话内容复制它没有意义。两处接入均位于 Rows.tsxProjectRowItem在 第 200-212 行 传入copyText{row.cwd}、copyLabel{t(copy)}、copiedLabel{t(hover.copied)}SessionNodeItem在 第 474-481 行 按空白与否传入copyText。本地化文案由浏览器自己的 locale seat 提供——locales.ts 中英文为Copy/Copied中文为复制/已复制。注意copyLabel与copiedLabel位于 Workspace 包的字典而不是公共的已复制文案因为这是 Workspace 特有的措辞不应改动所有既有复制控件。指针按下与激活两个分离的契约设计中最精妙的部分是按下press与激活activation是两个相互独立的契约它们共同决定了悬停卡在复制交互下的行为卡片内的指针按下用于开启文本选择不关闭卡片。悬停卡是通过 portal 渲染到document.body的但它是 wrapper 的 React 子节点因此卡片上的 capture 阶段按下也会到达 wrapper 的关闭处理器。源码在 HoverCard.tsx 用cardRef.current?.contains(e.target)判断按下点是否在卡片内在卡片内的按下保持卡片挂载从而允许文本选择拖拽从第一次 pointerdown 开始。完成的、非折叠的、与卡片相交的选区会抑制指针点击激活。onClick处理器在 第 147-157 行 检查window.getSelection()若存在非折叠选区且任一selection range 与卡片相交intersectsNode兼容 Firefox 的多 range 选区则直接返回、不触发复制——用户框选完文本后的点击不会意外触发复制。普通点击或按钮键激活复制。选区不存在、已折叠或位于卡片之外时点击会写入剪贴板Enter与Space键在 第 158-164 行 被preventDefault后触发同样的复制流程。锚点区域的按下仍然立即关闭卡片。按下发生在 wrapper行本身上时无需等待 owner 翻转disabled立即清除挂起的打开定时器并关闭卡片——这与 Menu 的行为保持一致。剪贴板拒绝时不宣称成功。共享助手writeClipboard只在宿主导航器确认接受写入时才返回true拒绝时卡片保留原始内容不显示任何成功状态。共享剪贴板助手复制写入走的是公共的 clipboard.tswriteClipboard与 Web UI 的其他复制控件TerminalBlock、CodeBlock、DiffBlock、SearchBlock 等共享优先使用异步navigator.clipboard.writeText权限被拒或 iframe 策略拦截时捕获异常并返回false不冒充成功对缺少异步 API 的宿主jsdom、非安全上下文回退到execCommand(copy)创建固定定位的只读textarea、选中文本、调用exec(copy)最终移除该元素两种路径都失败时返回false调用方据此保持原内容。成功反馈一秒窗口、高度保持、随卡片清理复制成功后的反馈状态机由三个 ref 与一个copiedstate 管理第 35-52 行、第 124-136 行高度保持写入选中的高度读自card.offsetHeight反馈渲染时通过minHeight保留该高度避免卡片内容从多行预览切换到居中短文本时发生跳动CSS 见 HoverCard.module.css 的.feedback与.copied一秒窗口setTimeout(clearCopied, 1000)重复激活不会重写也不会延长窗口copyingRef在写入飞行中合并并发激活随卡片关闭/卸载清理close()与卸载 effect 都会递增copyEpochRefepoch异步写入完成后若 epoch 已变化、组件已卸载或卡片已关闭则不会再渲染成功状态第 127-135 行状态播报wrapper 内渲染一个视觉隐藏的rolestatus元素第 202 行复制成功时向屏幕阅读器播报copiedLabel。测试覆盖行为契约的守护聚焦组件测试 hover-card.client.spec.tsx 用 jsdom fake timers 完整钉住了上述每一条契约打开时序悬停 500ms默认openDelayMs可自定义后打开、定位在锚点右侧、gap 内的重新进入不重启 dwell、宽限期POINTER_GRACE_MS 200见 pointer-grace.ts后关闭选区优先级卡片内的按下不关闭卡片完成的卡片内选区抑制点击复制含 Firefox 多 range 场景卡片外的非折叠选区不阻塞本卡复制激活语义按钮可访问名称为Copy path: /full/pathEscape不触发、Enter/Space触发成功反馈期间重复点击只写入一次反馈 1 秒后恢复原内容并清空minHeight失败路径剪贴板拒绝写入时内容保持、无成功标签写入飞行中卸载或关闭后完成的写入不会再产生反馈挂起的打开/反馈定时器随卸载清除几何与定位底部越界时按真实卡片高度回夹window.innerHeight - h - 8scroll/resize 时重新定位。真实浏览器场景则由 Workspace 的端到端快照验证英文标签、稳定反馈高度与浏览器剪贴板见设计笔记 Consequences 一节。备选方案与权衡设计笔记记录了三条被否决的路径帮助我们理解最终契约的取舍复制卡片的渲染textContent——会把主值与创建时间/运行状态拼接使剪贴板载荷依赖呈现与本地化被否决在两个 Workspace 卡体内各自实现剪贴板状态——两个消费者会重复宿主导航器回退、键盘行为、定时器所有权与成功渲染而激活表面本应由卡片拥有被否决把公共中文copied标签从复制成功改为已复制——会为满足一次卡片交互而改动所有既有复制控件最终改为由 Workspace 字典持有卡片专属措辞。结论HoverCard的点击复制功能在通用原语与消费者专属语义之间划出了一条清晰边界原子组件负责激活表面、剪贴板写入、失败判定与一秒成功反馈消费者Workspace 浏览器负责决定复制什么载荷、提供哪套本地化文案。指针按下保持卡片以支持文本选择、非折叠选区优先于点击激活、锚点按下立即关闭、拒绝写入不宣称成功——这四条契约共同保证了复制交互不会破坏既有的悬停预览与文本选择体验。若要在其他场景复用该能力只需向HoverCard传入copyText可选与必需的copyLabel/copiedLabel并遵守载荷必须是真实内容而非占位/拼接文本的原则对应契约可参照 hover-card.client.spec.tsx 逐条验证。赞分享人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载相关推荐DeepSeek Harness 悬浮卡片一键复制HoverCard 激活语义、剪贴板写入与无障碍反馈的实现剖析DeepSeek Harness 悬浮卡片一键复制HoverCard 激活语义、剪贴板写入与无障碍反馈的实现剖析 本文聚焦 DeepSeek Harness人工智能AI AgentAgent 框架DeepSeek告别频繁跳转GitHub Hovercard 悬停卡片全攻略告别频繁跳转GitHub Hovercard 悬停卡片全攻略 还在为查看GitHub用户资料、仓库信息频繁切换页面每次想了解issue详情或提交记录都要新开deepseek-harness Think 行交互契约用 expandOnRowClick 策略构建单一可访问披露目标deepseek harness Think 行交互契约用 expandOnRowClick 策略构建单一可访问披露目标 本文基于 deepseek harn人工智能AI AgentAgent 框架DeepSeek创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表