Files
superwork/vscode/webview-ui/src/codeReader/kindIcons.tsx
T
cruldra ec34ace7cf 🐛 fix(vscode): 悬停提示不用原生 title,webview 统一用自绘提示框,代码阅读的种类图标停上去能看到种类名
VS Code 1.139 带的 Electron 43 在 macOS 上只在鼠标压着带 title 的元素自身边缘时才弹原生提示,
停在它里面的图标、文字上不弹(electron/electron#49843,Electron 38 起)。种类图标 20px 的框
几乎被 16px 的图形占满,所以基本看不到种类名;块右上角按钮同样受影响。页面上核对过:图标中心点
命中的是图标里的线条,没有盖在上面的东西。

- components/ui/tooltip.tsx 改成整页只挂一次的 TooltipHost:元素只写 data-tooltip,事件统一交给它;
  样子照 VS Code 悬停框(editorHoverWidget 那组变量、widget-shadow 阴影),停 500ms 才弹、弹着时换元素
  立刻换,移开 / 按下 / 按键 / 滚动收起;键盘聚焦立刻弹,提示不是元素自己的名字时挂 aria-describedby
- 代码阅读里所有 title(种类图标、块按钮、筛选栏、问答区、中文名的「原名」)改成 data-tooltip;
  SelectMenu 的 title 属性改名 tooltip;看板工单详情原来包一层的 Tooltip 也改成 data-tooltip
- 何时弹 / 收的规则抽成纯函数加测试;更新代码阅读 spec
2026-09-27 21:21:13 +08:00

95 lines
2.8 KiB
TypeScript

import type { LucideIcon } from 'lucide-react'
import type { ReactElement } from 'react'
import type { BlockKind, BlockView, KindIconName } from './types'
import {
Box,
Braces,
CalendarClock,
Code,
CornerDownLeft,
CornerDownRight,
Database,
Globe,
Import,
ListOrdered,
Lock,
MessageSquareText,
Package,
Repeat,
ServerCog,
Shield,
ShieldAlert,
ShieldCheck,
Split,
SquareFunction,
Tag,
TriangleAlert,
Variable,
} from 'lucide-react'
/** 插件定义的这组种类图标,每个名字一个 lucide 图标(逐个 import,打包只带这些)。 */
export const KIND_ICON_COMPONENTS: Record<KindIconName, LucideIcon> = {
'import': Import,
'square-function': SquareFunction,
'box': Box,
'braces': Braces,
'list-ordered': ListOrdered,
'triangle-alert': TriangleAlert,
'tag': Tag,
'lock': Lock,
'variable': Variable,
'split': Split,
'corner-down-right': CornerDownRight,
'repeat': Repeat,
'shield': Shield,
'shield-alert': ShieldAlert,
'shield-check': ShieldCheck,
'corner-down-left': CornerDownLeft,
'code': Code,
'message-square-text': MessageSquareText,
'database': Database,
'package': Package,
'server-cog': ServerCog,
'calendar-clock': CalendarClock,
'globe': Globe,
}
/**
* 内置种类的图标:块左边只画图标,名字是悬停提示。
* 同一类语义共用一个颜色(codeReader.css 的 --cr-kind-*:常量 / 变量 / 字段都是数据,尝试 / 捕获都是异常处理),图标区分具体是哪种。
*/
export const KIND_ICONS: Record<BlockKind, KindIconName> = {
import: 'import',
function: 'square-function',
class: 'box',
type: 'braces',
enum: 'list-ordered',
exception: 'triangle-alert',
field: 'tag',
const: 'lock',
variable: 'variable',
if: 'split',
else: 'corner-down-right',
loop: 'repeat',
try: 'shield',
catch: 'shield-alert',
finally: 'shield-check',
return: 'corner-down-left',
statement: 'code',
comment: 'message-square-text',
}
/**
* 块左边的种类:只画图标,和一行字等高(20px 的框、16px 的图形),颜色是种类色(--kind)。图标是库规则给的(badge.icon),
* 没有就是内置种类的(KIND_ICONS,没带 badge 的块 kind 是 BlockKind);名字(翻译插件给种类起的,库规则的种类是规则给的)
* 写在悬停提示(data-tooltip,见 components/ui/tooltip.tsx)和读屏念的 aria-label 里。
*/
export function KindIcon({ block, name }: { block: Pick<BlockView, 'kind' | 'badge'>, name: string }): ReactElement {
const Icon = KIND_ICON_COMPONENTS[block.badge?.icon ?? KIND_ICONS[block.kind as BlockKind]]
return (
<span className="cr-kind flex size-5 shrink-0 items-center justify-center" role="img" data-tooltip={name} aria-label={name}>
<Icon size={16} strokeWidth={2.2} aria-hidden />
</span>
)
}