关于 data-visualization
面向开发者的数据可视化技能,适用于仪表板和报告。内容涵盖图表选择、响应式 Recharts 模式、无障碍替代方案以及加载和空状态。
主要功能
- 01按数据特点选择图表类型
- 02复用现有图表库和设计令牌
- 03构建响应式 Recharts 图表
- 04为屏幕阅读器提供数据替代内容
- 05处理加载与空状态
适用场景
- 01在仪表板中添加趋势图
- 02在统计数据旁展示迷你图
- 03避免仅依赖颜色提示并改善图表无障碍性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kensaurus/ skills --skill data-visualization安装后在 Claude Code 中输入/data-visualization确认已加载。
附带文件references/d3-and-accessibility.mdreferences/recharts.md
详细介绍
数据可视化技能
自由度:混合。 图表类型和编码 [高自由度];
现有库/令牌探测和无障碍回退 [低自由度 — 严格执行]。
如何推理
- 观察 — 现有图表库、令牌、数据形状
- 解读 — 复用组件还是新图表类型
- 分类 — 折线图/柱状图/面积图/环形图/迷你图/表格回退
- 判断严重性 — 无法访问或缺少空状态的图表,比缺少渐变更严重
示例
观察:
package.json中有 recharts;没有src/components/charts;令牌定义了--primary。 解读: 复用 Recharts 和令牌,而不是 D3。 分类:ResponsiveContainer折线图 + sr-only 表格;加载时显示骨架屏。 验证: 可调整大小;存在屏幕阅读器表格;没有引入第二个图表库。
报告前自我检查
- 现有库 — 已搜索
package.json;没有添加第二个图表库 - 无障碍 — 存在 sr-only 表格或文本替代内容
- 状态 — 已处理加载和空状态
- 职责归属正确 — 事件分类 →
audit-analytics;空状态/加载状态框架 →audit-ui-states
为仪表板和报告创建美观、无障碍且可交互的数据可视化。
产品事件覆盖情况(“我们是否在跟踪正确的事件?”)由 audit-analytics 负责,
而不是此技能。图表的空状态/加载状态框架由 audit-ui-states 负责。
先检查现有内容 [低自由度 — 严格执行]
创建任何可视化内容之前,请先确认:
- 检查是否已有图表库:
cat package.json | grep -i "recharts\|chart\|d3\|visx\|nivo\|tremor"
rg "LineChart|BarChart|PieChart" --type tsx -l | head -10
- 检查是否已有图表组件:
ls -la src/components/charts/ src/components/dashboard/ 2>/dev/null
rg "ResponsiveContainer|Chart" --type tsx | head -10
- 检查是否已有设计令牌:
cat tailwind.config.* | grep -A10 "chart\|colors"
原因: 使用现有图表库和样式规范。
Recharts(推荐用于 React) [高自由度]
- 将每个图表都包装在
ResponsiveContainer width="100%"中;设置固定的height。 - 使用令牌设置样式:
hsl(var(--primary))、fill-muted-foreground、stroke-muted;不要使用硬编码的十六进制值。 - 隐藏坐标轴线和刻度线(
tickLine={false} axisLine={false});格式化 Y 轴刻度($、%)。 - 自定义
Tooltip内容使用bg-background border rounded-lg,以匹配主题。 - 图表类型:折线图(随时间变化的趋势)、柱状图(
radius={[4,4,0,0],突出显示最新的Cell)、面积图(渐变<defs>填充)、环形图(innerRadius/outerRadius+ 中心Label显示总量)。
'use client'
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts'
export function RevenueChart({ data }: { data: { month: string; revenue: number }[] }) {
return (
<ResponsiveContainer width="100%" height={350}>
<LineChart data={data}>
<XAxis dataKey="month" tickLine={false} axisLine={false} className="text-xs fill-muted-foreground" />
<YAxis tickLine={false} axisLine={false} tickFormatter={(v) => `$${v}`} />
<Tooltip cursor={{ stroke: 'hsl(var(--muted))' }} />
<Line type="monotone" dataKey="revenue" stroke="hsl(var(--primary))" strokeWidth={2} activeDot={{ r: 6 }} />
</LineChart>
</ResponsiveContainer>
)
}
包含自定义提示框的完整折线图、柱状图、渐变面积图和环形图组件:references/recharts.md §折线图、§柱状图、§面积图、§饼图/环形图。
迷你图 [高自由度]
- 使用只有一个
Line的LineChart,设置dot={false}、strokeWidth={1.5},不显示坐标轴,高度约为 40。 - 在组件内部将
number[]映射为{ index, value },这样调用方只需传入普通数组。 - 将其放在统计值旁边的
w-20区域中,不要单独放在卡片里。
Sparkline 组件和统计卡片用法:references/recharts.md §迷你图。
带趋势的统计卡片 [高自由度]
- 使用
rounded-xl border bg-card p-6;标题使用text-muted-foreground,数值使用text-3xl font-semibold。 - 趋势箭头 +
Math.abs(change)%;上升显示绿色,下降显示红色;将相同颜色传给迷你图。 sparklineData是可选的;仅在存在时渲染迷你图。
StatCard 组件:references/recharts.md §带趋势的统计卡片。
实时数据更新 [高自由度]
- 使用
setData(prev => [...prev, point].slice(-N))追加数据;保留有界窗口(约 20 个数据点)。 - 设置
isAnimationActive={false}和固定的YAxis domain,避免图表随每次更新跳动。 - 在 effect 清理函数中清除定时器或取消 socket 订阅。
RealtimeChart 组件:references/recharts.md §实时数据更新。
用于自定义可视化的 D3.js [HIGH freedom]
- 仅当 Recharts 无法呈现所需图表标记时才使用 D3;不要在已有图表库旁再添加 D3。
- 将内容渲染到通过
ref引用的<svg>中;在useEffect中执行,并在数据变更、重绘之前调用svg.selectAll('*').remove()。 - 类别使用
scaleBand,数值使用scaleLinear().nice();通过clientWidth/clientHeight获取尺寸,并留出边距。 - 从基线开始使用
.transition().duration(750)添加动画;使用相同的hsl(var(--primary))令牌设置颜色。
完整的 D3 条形图组件:references/d3-and-accessibility.md §D3.js 自定义条形图。
无障碍 [LOW freedom — run exactly]
- 使用
<div role="img" aria-label="...">包裹图表,并说明图表展示的内容及其范围。 - 将 SVG 图表标记为
aria-hidden="true";通过带有<caption>的sr-only<table>提供数据。 - 颜色绝不能是唯一的编码方式:应搭配标签、标记或图例。
<div role="img" aria-label="Revenue chart showing monthly data from January to December">
<ResponsiveContainer><LineChart data={data} aria-hidden="true">{/* ... */}</LineChart></ResponsiveContainer>
<table className="sr-only">
<caption>Monthly Revenue Data</caption>
<thead><tr><th>Month</th><th>Revenue</th></tr></thead>
<tbody>{data.map((d) => <tr key={d.month}><td>{d.month}</td><td>${d.revenue}</td></tr>)}</tbody>
</table>
</div>
完整的无障碍代码块:references/d3-and-accessibility.md §无障碍。
验证 [LOW freedom — do not skip]
创建可视化后:
- 响应式 → 图表在所有屏幕上都能正确调整大小
- 无障碍 → 提供屏幕阅读器替代内容
- 性能 → 对大型数据集使用虚拟化/采样
- 加载状态 → 数据加载时显示骨架屏
- 空状态 → 无数据时显示有意义的提示
- 颜色对比度 → 符合 WCAG 指南
- 工具提示 → 悬停时提供详细数据