data-dashboard
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSkill: Data dashboard
Skill:数据仪表板
Step 0 — is the kit here? This skill reads files from the kit. Check once:Onls ${CLAUDE_SKILL_DIR}/../../../tokens >/dev/null 2>&1 && echo KIT_OK || echo KIT_MISSINGonly the skill folders were installed, which is whatKIT_MISSINGdoes. Say so plainly, point the user atnpx skills addor the plugin install, and stop. Do not guess the contents of a file you could not open.npx ux-ui-agent-skills init
A dashboard is the hardest screen to keep honest: it is dense, it is mostly
non-text, and almost every default makes it worse. This is the recipe that
produced and , both of which pass every
gate in both themes.
${CLAUDE_SKILL_DIR}/../../../examples/showcase/${CLAUDE_SKILL_DIR}/../../../examples/terminal/Step 0 — 工具包是否在这里? 此 skill 会从工具包中读取文件。检查一次:如果显示ls ${CLAUDE_SKILL_DIR}/../../../tokens >/dev/null 2>&1 && echo KIT_OK || echo KIT_MISSING,说明只安装了 skill 文件夹,这正是KIT_MISSING执行的操作。直接说明这一点,引导用户运行npx skills add或安装插件,然后停止。不要猜测任何 无法打开的文件内容。npx ux-ui-agent-skills init
仪表板是最难做到数据可信的界面:它信息密集,主要由非文本内容构成,而且几乎每个默认设置都会让它更糟。下面的配方生成了 和 ,这两个参考实现都能在明暗两种主题下通过所有检查。
${CLAUDE_SKILL_DIR}/../../../examples/showcase/${CLAUDE_SKILL_DIR}/../../../examples/terminal/1. Decide the brief before drawing anything
1. 开始绘制前先确定需求
Answer these in one line each, or them out of the user:
/grill-me- Who reads this, and what decision do they make from it? A revenue console for an operator and a trading desk for a dealer look nothing alike.
- What is the one number that leads? A dashboard without a lead is a wall.
- What is the update cadence? Hourly figures get a "last run" line. Live figures get a tape and a timestamp per row.
- How dense is honest? A terminal earns 12 panels. A weekly report does not.
用一行分别回答以下问题,或者使用 向用户逐一追问:
/grill-me- 谁会阅读它?他们会据此做出什么决策? 面向运营人员的营收控制台与交易员的交易台完全不同。
- 哪个数字是主导指标? 没有主指标的仪表板只是一堵墙。
- 更新频率是多少? 每小时更新的数据应显示一行“上次运行”信息。实时更新的数据则应提供行情带,并为每行标注时间戳。
- 怎样的密度才算合理? 交易终端可以容纳 12 个面板,周报则不行。
2. Layout sequence, not a grid of equal cards
2. 按区带安排布局,而不是排列等分卡片
Four equal stat cards is the single loudest tell that nobody designed this.
Compose in bands, each a different shape:
| Band | Content | Why |
|---|---|---|
| 1 | Hero metric at 3x body size + its own chart, spanning most of the width | The eye lands once |
| 2 | Two or three secondary figures, stacked or narrow | Quiet by construction |
| 3 | Three different chart shapes side by side (donut, ranked bars, sparklines) | Variety reads as intent |
| 4 | A table that really sorts, plus a feed or log | Detail after summary |
| 5 | A footer line that ends the page | A page must end on purpose |
Use a 12-column grid with explicit spans ( / ), collapsing to 6
then 1. Never for the primary bands - it produces exactly
the equal-card wall you are avoiding.
span 8span 4repeat(auto-fit, …)四个大小相同的统计卡片,是没人真正设计过界面的最刺眼标志。
应按区带编排,每个区带采用不同的形状:
| 区带 | 内容 | 原因 |
|---|---|---|
| 1 | 字号为正文 3 倍的主导指标及其专属图表,横跨大部分宽度 | 让视线只落一次 |
| 2 | 两个或三个次要指标,纵向排列或使用较窄区域 | 天然更安静 |
| 3 | 三种不同的图表形状并排展示,例如环形图、排名条形图和迷你图 | 多样性传达出设计意图 |
| 4 | 真正支持排序的表格,加上信息流或日志 | 摘要之后再呈现细节 |
| 5 | 用于结束页面的页脚行 | 页面必须有明确的结束方式 |
使用带有明确跨度的 12 栏网格( / ),然后依次折叠为 6 栏和 1 栏。绝不要在主要区带使用 ——它恰好会生成你要避免的等分卡片墙。
span 8span 4repeat(auto-fit, …)3. The chart inventory
3. 图表清单
All of these are plain inline SVG with , sized by CSS, filled from
. No chart library, no runtime dependency.
viewBox--color-chart-*| Chart | Geometry | Use it for |
|---|---|---|
| Bar / column | | Discrete periods |
| Candlestick | | OHLC price |
| Volume | Bars under the price chart, same x-scale, | Conviction behind a move |
| Moving average | | Trend through noise |
| Line / sparkline | | Trend in a cell |
| Area / stacked area | | Composition over time |
| Depth | Two cumulative area paths mirrored around the mid | Book liquidity |
| Waterfall | Floating | Attribution |
| Donut | | Share of a whole, 3-5 slices |
| Radial gauge | Same trick, | One value against a limit |
| Scatter / bubble | | Two measures plus weight |
| Correlation matrix | HTML table, cell tint via | Pairwise relationships |
| Heatmap | HTML table or | Cohorts, calendars |
| Order book | HTML table with a depth bar per row | Bids and asks |
Generate the geometry, do not hand-place it. Write a small deterministic
script (a seeded walk) that emits the SVG elements, then paste the output in.
Hand-typed coordinates drift and cannot be regenerated.
所有图表都使用带 的纯内联 SVG,由 CSS 控制尺寸,并使用 填充。不依赖图表库或任何运行时依赖。
viewBox--color-chart-*| 图表 | 几何结构 | 适用场景 |
|---|---|---|
| 条形图 / 柱状图 | 每个分桶使用一个 | 离散周期 |
| K线图 | 每个周期使用一条 | OHLC 价格 |
| 成交量图 | 价格图下方的柱形,使用相同的 x 轴刻度和 | 反映价格变动背后的交易强度 |
| 移动平均线 | 覆盖在 K 线上方的 | 从噪声中呈现趋势 |
| 折线图 / 迷你图 | | 单元格内的趋势 |
| 面积图 / 堆叠面积图 | 每个区带使用一个 | 随时间变化的构成 |
| 深度图 | 围绕中线镜像排列的两条累计面积路径 | 订单簿流动性 |
| 瀑布图 | 每个步骤使用一个浮动 | 归因分析 |
| 环形图 | 使用 | 整体占比,3 至 5 个分段 |
| 径向仪表盘 | 使用相同方法,配合 | 单一数值与上限的对比 |
| 散点图 / 气泡图 | 使用 | 两个度量及其权重 |
| 相关性矩阵 | HTML 表格,通过 | 两两关系 |
| 热力图 | HTML 表格或 | 群组、日历 |
| 订单簿 | HTML 表格,每行包含一个深度条 | 买盘和卖盘 |
生成几何结构,不要手动定位。 编写一个小型确定性脚本,使用固定种子的随机游走生成 SVG 元素,然后粘贴输出。手写的坐标会产生偏移,而且无法重新生成。
4. Domain correctness is part of craft
4. 领域正确性也是专业水准的一部分
Gates cannot catch a chart that is drawn beautifully and means nothing. Check by
hand:
- A correlation matrix is symmetric and its diagonal is exactly 1. Random values in both triangles is an instant tell to anyone who reads one for a living.
- A stacked area sums to the total; bands must not cross or leave gaps. The usual bug is reversing the baseline by index instead of by coordinate, which shows as dark wedges between bands.
- A waterfall needs connectors, and the closing bar must equal opening plus the steps.
- Depth rises away from the mid on both sides; it never falls.
- A donut whose segments do not total the whole is a pie chart lying.
自动检查无法发现一幅绘制精美却毫无意义的图表。必须手动检查:
- 相关性矩阵是对称的,且对角线上的值恰好为 1。在两个三角区域都填入随机值,会立刻向专业读者暴露问题。
- 堆叠面积图各层之和必须等于总量;各层不能交叉,也不能留有空隙。常见 bug 是按索引反转基线,而不是按坐标反转,这会在各层之间显示为深色楔形。
- 瀑布图必须包含连接线,结束柱必须等于起始值加上各步骤的变化值。
- 深度图从中线向两侧越远越高,绝不能下降。
- 如果环形图各分段之和不等于整体,那就是一张在撒谎的饼图。
5. Accessibility contract, per chart
5. 每种图表的无障碍契约
- Every SVG gets plus either
role="img"oraria-label+<title>referenced by<desc>. Say what the chart shows, not that it is a chart: "Range 182.06 to 200.10, closing at 187.84" beats "price chart".aria-labelledby - Never encode meaning in colour alone. Green with a and an arrow; red with a
+. Up and down also carry a word in the table cell.- - Tables get (use
<caption>when the panel header already says it),.sr-only/scope="col", andscope="row"only if clicking really sorts.aria-sort - Sortable headers, range tabs and theme toggles all declare state - so they must
change it on a real click. clicks them and checks.
verify_interactive.mjs
- 每个 SVG 都要设置 ,并提供
role="img",或提供由aria-label引用的aria-labelledby和<title>。说明图表展示的内容,不要只说它是一个图表:“区间从 182.06 到 200.10,收于 187.84”优于“价格图表”。<desc> - 绝不能只依赖颜色传达含义。绿色搭配 和箭头,红色搭配
+。在表格单元格中,上涨和下跌还应带有文字。- - 表格需要 ;当面板标题已经说明表格用途时,可以使用
<caption>。还需要.sr-only/scope="col",并且只有在点击操作确实会触发排序时才使用scope="row"。aria-sort - 所有可排序表头、范围选项卡和主题切换器都会声明状态,因此必须响应真实点击并改变状态。会点击并检查它们。
verify_interactive.mjs
6. The traps that only appear when you measure
6. 只有在实际测量时才会暴露的陷阱
Every one of these was found on a screen that looked finished. The first group a
gate caught; the ones marked "no gate sees it" were caught by opening the
screenshot and looking, which is why that step is not optional:
- A chart palette is not a text palette. White initials on measured 2.65:1 in dark. Chart colours are tuned for large filled shapes.
--color-chart-4 - Success green as text on a raised surface measured 4.43:1 - four hundredths short of AA. Put the colour on the icon and the sign; keep the text neutral.
- axe must not run mid-transition. Disable transitions before flipping the theme, or contrast is sampled while colours are still moving.
- Dense tables do not fit a phone. Drop the column a phone can lose - the sparkline, the derived value - in a media query, and say so in a comment. Do not shrink type below the scale.
- Stagger comes from a token: , never a typed millisecond.
calc(var(--duration-fast) * 0.6 * n) - A grid row stretches its items. Two fields side by side where only one has
a hint: the hint-less control grows to match the taller column and the two
inputs end up different heights. Set on the field and an explicit
align-content: starton the control. Measure the heights in the render - the difference is obvious in a screenshot and invisible in the markup.block-size - The same stretch hits whole panels, and no gate sees it. A row is as tall as
its tallest panel, and the short one packs its content to the top and ends in a
bordered void - a heatmap panel with 130px of nothing under the caption, a right
column that stops two panels short of the map beside it. Every panel in a row
has to say which it is: one child absorbs the slack
(, and that child's own tracks go
grid-template-rows:auto minmax(0,1fr)so its rows grow too), or the rows share it out (minmax(<min>,1fr)), or the short column earns another panel. Screenshot the row and look at the bottom edge of each panel; this never shows up in the markup.align-content:space-between - silently drops a column, and no gate sees it. Three gauges in a panel about 340px wide with
auto-fitresolved to two tracks and orphaned the third beside an empty cell. When the count is fixed and meaningful, writeminmax(min(100%,7rem),1fr)and give narrow widths their own rule.repeat(3,minmax(0,1fr)) - A category chart needs its categories on the page, and no gate sees it. A
Pareto of five defect types whose names live only in the is a row of anonymous bars to everyone looking at it. Put the labels under the bars - lay the plot out on an even pitch inside its viewBox so a matching grid of labels lines up without a second coordinate system.
aria-label - An needs a positioned ancestor. Inside a scroller it otherwise resolves against the initial containing block, lands outside the viewport, and inflates the document's scroll width by hundreds of pixels.
.sr-only - A zero-area element that only has area while it animates reads as content
lost under . Give a radar sweep a wedge, not a 1px line.
prefers-reduced-motion - Never reuse a class name across layout and colour. as both a four-column span and the fourth chart colour painted an entire panel pink.
.c4
以下每一项都曾出现在一个看起来已经完成的界面上。第一组问题由自动检查发现;标记为“no gate sees it”的问题,则是通过打开截图并亲眼查看发现的,因此这一步不可省略:
- 图表调色板不是文本调色板。 深色模式下,上的白色首字母对比度仅为 2.65:1。图表颜色针对大面积填充形状调校。
--color-chart-4 - 凸起表面上的成功绿色文本对比度为 4.43:1——距离 AA 标准还差 0.04。把颜色放在图标和正负号上,文字保持中性。
- 不能在过渡过程中运行。切换主题前禁用过渡,否则采样对比度时颜色仍在变化。
axe - 密集表格不适合手机。通过媒体查询移除手机端可以舍弃的列,例如迷你图或派生值,并在注释中说明。不要把字号缩小到低于既定尺度。
- 错落延迟必须来自 token:,绝不能手写毫秒值。
calc(var(--duration-fast) * 0.6 * n) - 网格行会拉伸其中的项目。两个字段并排且只有一个带提示文字时,没有提示的控件会被拉高,与较高一列对齐,最终两个输入框高度不同。在字段上设置 ,并在控件上设置明确的
align-content: start。在渲染结果中测量高度——差异在截图中显而易见,在标记中却看不出来。block-size - 同样的拉伸问题也会影响整个面板,而且没有任何检查能够发现。一行的高度取决于其中最高的面板,较矮的面板会把内容堆在顶部,底部留下带边框的空白——例如热力图标题下方残留 130px 空白,或右侧列比旁边的地图少两个面板的高度。每一行中的每个面板都必须明确如何处理剩余空间:由一个子项吸收剩余空间(,并让该子项内部的轨道使用
grid-template-rows:auto minmax(0,1fr),使其各行也能增长),由各行分摊剩余空间(minmax(<min>,1fr)),或者给较矮的一列再增加一个面板。对这一行截图并检查每个面板的底边;这个问题在标记中永远不会显现。align-content:space-between - 会悄悄丢弃一列,而且没有任何检查能够发现。在一个约 340px 宽的面板中放置三个仪表盘时,
auto-fit会解析为两个轨道,导致第三个仪表盘与一个空单元格并排成为孤立项。当数量固定且具有实际意义时,应使用minmax(min(100%,7rem),1fr),并为较窄宽度设置单独规则。repeat(3,minmax(0,1fr)) - 分类图表必须把分类名称呈现在页面上,而且没有任何检查能够发现。一个展示五种缺陷类型的 Pareto 图,如果名称只存在于 中,那么对所有看到它的人来说就只是一排匿名条形图。应把标签放在条形图下方,并在 viewBox 内部按等距布局绘图区,使匹配的标签网格无需第二套坐标系统即可对齐。
aria-label - 需要一个已定位的祖先元素。否则,在滚动容器内,它会相对于初始包含块解析,落到视口之外,并使文档的滚动宽度增加数百像素。
.sr-only - 仅在动画期间才具有面积、静止时面积为零的元素,会让 用户误以为内容丢失。雷达扫描应使用楔形区域,而不是 1px 的线条。
prefers-reduced-motion - 绝不能在布局和颜色之间复用同一个 class 名。如果既表示四栏跨度,又表示第四种图表颜色,就可能把整个面板涂成粉红色。
.c4
7. The loop
7. 执行循环
bash
node ${CLAUDE_SKILL_DIR}/../../../scripts/measure_render.mjs <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/measure_render.mjs --dark <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_states.mjs <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/axe_audit.mjs --dark <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_responsive.mjs <file> --scale=1.25
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_interactive.mjs <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/slop_tells.mjs --strict <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/taste_audit.mjs --strict <file>Then screenshot it and look, in both themes, at 1600 and 390 wide. The gates
will pass a chart that is drawn wrong. A correlation matrix that is not
symmetric is 16/16 green and still embarrassing.
Worked references, both gate-verified: (revenue
console) and (trading desk, ten chart types).
${CLAUDE_SKILL_DIR}/../../../examples/showcase/index.html${CLAUDE_SKILL_DIR}/../../../examples/terminal/index.htmlbash
node ${CLAUDE_SKILL_DIR}/../../../scripts/measure_render.mjs <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/measure_render.mjs --dark <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_states.mjs <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/axe_audit.mjs --dark <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_responsive.mjs <file> --scale=1.25
node ${CLAUDE_SKILL_DIR}/../../../scripts/verify_interactive.mjs <file>
node ${CLAUDE_SKILL_DIR}/../../../scripts/slop_tells.mjs --strict <file> && node ${CLAUDE_SKILL_DIR}/../../../scripts/taste_audit.mjs --strict <file>然后在两种主题下,分别以 1600 和 390 的宽度截图并亲自查看。自动检查可能让绘制错误的图表通过。一个不对称的相关性矩阵会显示 16/16 全绿,却依然令人尴尬。
经过各项检查的实战参考:(营收控制台)和 (交易台,包含十种图表类型)。
${CLAUDE_SKILL_DIR}/../../../examples/showcase/index.html${CLAUDE_SKILL_DIR}/../../../examples/terminal/index.html