SuperAPI AI 工具集

ship-accessible-charts

前端与建站

查看项目

更新于 10-16 04:50

技能介绍

Ship Accessible Charts 是一份发布前工作流程:触发 → 检查 → 决策 → 构建 → 验证。只有当图表的语义替代表示、适配器生命周期、SSR 策略、渲染器、导出、包边界和销毁流程都在贴近真实消费者的场景中得到验证,图表才算真正“交付”。

无障碍检查

检查:名称要能标识被比较的对象

期望示例:

const hostOptions = {
  definition,
  height: 320,
  initialWidth: 640,
  ariaLabel: 'Weekly downloads for Core and React packages',
  ariaDescription: 'Values are seven-day totals. Missing weeks appear as gaps.',
}

失败条件:标签只写“chart”,或重复可见标题却没有指标,或者遗漏比较对象与时间范围。

修复:写明指标、被比较的实体和时间范围;把结论与详细数值放在常规应用内容中。

检查:关键数值要有等价表示

期望:可见的标题与单位,当精确数值或应用决策依赖图表时,还要在邻近位置提供摘要或语义化表格。

失败条件:获取必要数值的唯一方式是指针悬停、颜色、动效或视觉估算。

修复:把相同的语义行或选定键绑定到应用文本/表格控件。

检查:每个交互都有非指针路径

期望:原生点键盘导航、用于自由光标和范围控件的语义化按钮/输入、可见焦点、取消/重置路径,以及有意义的已提交状态文本。

失败条件:透明指针覆盖层是唯一的控制面。

修复:在键盘契约匹配的地方使用一方控件,否则使用应用自有的语义化控件。

生命周期检查

检查:SSR 使用受支持的适配器和确定性输入

期望示例:

import {
  createChartRuntime,
  defineChart,
  lineY,
  renderChartSvg,
} from '@tanstack/charts'
import { scaleLinear } from '@tanstack/charts/scales/linear'
import { scaleUtc } from 'd3-scale'

interface TrafficRow {
  date: Date
  visits: number
}

const rows: readonly TrafficRow[] = [
  { date: new Date('2026-08-10T00:00:00Z'), visits: 820 },
  { date: new Date('2026-08-11T00:00:00Z'), visits: 910 },
]

const definition = defineChart({
  marks: [lineY(rows, { x: 'date', y: 'visits' })],
  scales: {
    x: { scale: scaleUtc },
    y: { scale: scaleLinear },
  },
})

const runtime = createChartRuntime<TrafficRow, Date, number>()
const scene = runtime.render(definition, { width: 720, height: 400 })

export const svg = renderChartSvg(scene, {
  ariaLabel: 'Daily traffic',
  idPrefix: 'daily-traffic',
})

runtime.destroy()

失败条件:definition 的构建读取了浏览器布局、随机值、本地时间或未解析的异步数据;或者所选的适配器不承诺支持 SSR。

修复:在渲染前解析数据,使用确定性的格式化和尺寸,并遵循所选适配器的参考文档。

检查:挂载、更新和清理保持由适配器负责

期望:每个已挂载的适配器实例对应一个 runtime;完整的不可变选项更新;在捕获值变化前定义保持稳定;卸载/断开时执行清理。

失败条件:应用代码在服务端渲染期间调用 DOM 测量或挂载浏览器宿主,或者在移除后仍保留观察器/监听器。

修复:使用适配器生命周期,或仅在浏览器拥有的挂载阶段调用 mountChart,并在拆除时调用 destroy()。

渲染器与导出检查

检查:渲染器选择与任务匹配

SVG:服务端可见几何、矢量导出、DOM 样式、常规交互图表。

Canvas:高场景数量或栅格优先输出;服务端输出无障碍外壳,而非像素。

静态 SVG:确定性服务端/导出产物,不带浏览器交互。

React Native SVG:明确的原生目标,需在设备级别验证。

检查:导出可复现

期望:明确的尺寸、主题/背景、作用域 ID、可移植的字体/资源、有意包含焦点,以及有意义的导出名称/描述。

失败条件:导出依赖当前响应式像素或无法访问的应用 CSS/资源。

修复:渲染明确的 scene,或按明确的产物策略进行序列化/栅格化。

常见错误

CRITICAL 使用通用的无障碍标签

错误:ariaLabel: 'Chart'。

正确:写明理解该图形所需的指标、实体、时间范围与单位。

通用标签只暴露一个可聚焦的图形,却没有有用的身份。

来源:docs/guides/accessibility.md

HIGH 让图表成为唯一表示

错误:要求通过悬停或视觉估算来获取精确的操作数值。

正确:从相同的语义数据/状态渲染摘要、表格或应用控件。

当精确数值至关重要时,图表表面只是补充。

来源:docs/guides/accessibility.md;归档的 responsive/accessibility 笔记

CRITICAL 在服务端渲染期间挂载浏览器宿主

错误:从服务端生命周期调用 mountChart 或适配器 DOM mount。

正确:通过受支持的 SSR 适配器或 renderChartSvg 预渲染确定性 scene,然后仅在真实元素存在后再挂载浏览器宿主。

测量和变更需要浏览器元素。较早的 Angular 变通方案尤其容易出现这种边界错误。

来源:GitHub issue 56;docs/guides/ssr-and-hydration.md

HIGH 把行为放在适配器 props 上

错误:

<Chart definition={chart} tooltip keyboard />

正确:

const interactive = defineChart(chart, { tooltip, keyboard: true })
<Chart definition={interactive} ariaLabel="Revenue by month" />

焦点、tooltip、键盘、控件、光标和 SVG 动画属于可复用的 definition;适配器负责表面生命周期和框架主体组合。当前的 definition API 取代了遗留的适配器行为 props。

来源:CHANGELOG.md 中的 chart-behavior 迁移;React chart 参考

HIGH 在原生环境中导入通用 barrel

错误:为每个原生图表使用 @tanstack/charts/universal。

正确:使用精确的 core mark/scale/scene 以及 @tanstack/charts/react-native 子路径,除非跨平台编写方式证明使用通用包是合理的。

精确导入可以保护 Metro 和原生声明环境,使其免受无关的浏览器和可选能力代码影响。

来源:API-FRICTION.md F-154、F-171、F-173、F-256;React Native 包 README

HIGH 张力:丰富交互与可移植渲染

DOM 便利性可能破坏静态 SVG、Canvas、原生、SSR 或键盘等价性。将语义保留在 definitions 和应用状态中;仅在呈现接缝处使用平台特定的 body/host 扩展。

另见:build-chart-interactions/SKILL.md 和 extend-tanstack-charts/SKILL.md

部署前摘要

  • 有意义的名称和简洁的描述。
  • 可见的单位、时间范围和来源上下文。
  • 在需要时提供精确数值摘要/表格。
  • 指针、键盘、触摸和取消/重置场景。
  • 减少动效和非颜色证据。
  • 受支持的 SSR 策略与确定性初始几何。
  • 稳定的 definition、mark、datum 和资源 ID。
  • 已验证挂载、更新、调整大小、字体重排和销毁。
  • 从打包后的消费者验证渲染器和导出行为。
  • 在适用时,在目标设备上验证原生声明。

参考资料

React

Preact

Vue

Solid

Svelte

Angular

Lit

Alpine

Octane

React Native

渲染器与导出

另见:debug-and-verify-charts/SKILL.md —— SSR、无障碍、渲染器和包声明需要消费者级别的证据。