♻️ refactor(vscode): 看板的悬停提示也改走 data-tooltip,插件网页只剩一条提示的路;lint 禁止原生 title

- 看板剩下的原生 title(顶栏按钮、工单卡片、工单详情、会话、Profile 表、改动文件树和 diff、属性表)全部改成 data-tooltip,
  禁用的按钮照样弹;只有图标、原来只靠 title 当名字的(审查勾、生成说明、属性说明的 i 图标、没头像的归属人)补上 aria-label
- 提示框按原文换行:摘修复弹框里「迁移」列的几个文件一行一个
- 代码阅读 Markdown 链接的标题写成 data-tooltip
- eslint 规则:网页 TSX 的 DOM 元素上写 title 报错,iframe 和组件自己的 title 属性不算
This commit is contained in:
cruldra committed 2026-09-27 21:39:15 +08:00
1 parent 1f7bf63e27
commit c8620e6e1b
15 files changed
+86 -46

No files matched your search

@@ -140,7 +140,7 @@ export function FileDiffPane({
<span
className="min-w-0 flex-1 truncate font-mono text-xs"
style={{ color: confirmed ? 'var(--vscode-descriptionForeground)' : 'var(--vscode-foreground)' }}
title={path}
data-tooltip={path}
>
{path}
</span>
@@ -148,7 +148,8 @@ export function FileDiffPane({
<button
type="button"
onClick={() => onToggleConfirm(!confirmed)}
title={confirmed ? '已审查,点击取消' : '标记为已审查'}
data-tooltip={confirmed ? '已审查,点击取消' : '标记为已审查'}
aria-label={confirmed ? '已审查,点击取消' : '标记为已审查'}
className="shrink-0"
style={{
color: confirmed
@@ -163,7 +164,9 @@ export function FileDiffPane({
type="button"
onClick={onGenerate}
disabled={generating}
title={generating ? '生成中…' : '生成本文件改动说明'}
data-tooltip={generating ? '生成中…' : '生成本文件改动说明'}
aria-label="生成本文件改动说明"
aria-busy={generating}
className="shrink-0 text-[var(--vscode-descriptionForeground)] hover:text-[var(--vscode-foreground)] disabled:opacity-60"
>
{generating ? <Loader2 className="size-3.5 animate-spin" /> : <Sparkles className="size-3.5" />}
@@ -70,7 +70,8 @@ export function FileTree({
e.stopPropagation()
onToggleDirConfirm(row.descendantFiles, !isConfirmed)
}}
title={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
data-tooltip={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
aria-label={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
className="shrink-0 transition-opacity"
style={{
opacity: isConfirmed || hoveredPath === row.path ? 1 : 0,
@@ -87,13 +88,13 @@ export function FileTree({
const isConfirmed = confirmed.has(row.path)
const isSelected = selectedPath === row.path
return (
// 文件行:点击选中 → 容器据此拉取并渲染右栏 diff;title 用完整路径。
// 文件行:点击选中 → 容器据此拉取并渲染右栏 diff;悬停提示是状态和完整路径。
<li
key={row.path}
onMouseEnter={() => setHoveredPath(row.path)}
onMouseLeave={() => setHoveredPath(p => (p === row.path ? null : p))}
onClick={() => onSelectFile(row.path)}
title={`${row.status} · ${row.path}`}
data-tooltip={`${row.status} · ${row.path}`}
className={`group flex cursor-pointer items-center gap-2 py-0.5 pr-2 ${
isSelected
? 'bg-[var(--vscode-list-activeSelectionBackground)] text-[var(--vscode-list-activeSelectionForeground)]'
@@ -114,7 +115,8 @@ export function FileTree({
e.stopPropagation()
onToggleFileConfirm(row.path, !isConfirmed)
}}
title={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
data-tooltip={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
aria-label={isConfirmed ? '已查看,点击取消' : '标记为已查看'}
className="shrink-0 transition-opacity"
style={{
opacity: isConfirmed || hoveredPath === row.path ? 1 : 0,