data-dashboard

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skill: Data dashboard

Skill:数据仪表板

Step 0 — is the kit here? This skill reads files from the kit. Check once:
ls ${CLAUDE_SKILL_DIR}/../../../tokens >/dev/null 2>&1 && echo KIT_OK || echo KIT_MISSING
On
KIT_MISSING
only the skill folders were installed, which is what
npx skills add
does. Say so plainly, point the user at
npx ux-ui-agent-skills init
or the plugin install, and stop. Do not guess the contents of a file you could not open.
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
${CLAUDE_SKILL_DIR}/../../../examples/showcase/
and
${CLAUDE_SKILL_DIR}/../../../examples/terminal/
, both of which pass every gate in both themes.
Step 0 — 工具包是否在这里? 此 skill 会从工具包中读取文件。检查一次:
ls ${CLAUDE_SKILL_DIR}/../../../tokens >/dev/null 2>&1 && echo KIT_OK || echo KIT_MISSING
如果显示
KIT_MISSING
,说明只安装了 skill 文件夹,这正是
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
/grill-me
them out of the user:
  • 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:
BandContentWhy
1Hero metric at 3x body size + its own chart, spanning most of the widthThe eye lands once
2Two or three secondary figures, stacked or narrowQuiet by construction
3Three different chart shapes side by side (donut, ranked bars, sparklines)Variety reads as intent
4A table that really sorts, plus a feed or logDetail after summary
5A footer line that ends the pageA page must end on purpose
Use a 12-column grid with explicit spans (
span 8
/
span 4
), collapsing to 6 then 1. Never
repeat(auto-fit, …)
for the primary bands - it produces exactly the equal-card wall you are avoiding.
四个大小相同的统计卡片,是没人真正设计过界面的最刺眼标志。 应按区带编排,每个区带采用不同的形状:
区带内容原因
1字号为正文 3 倍的主导指标及其专属图表,横跨大部分宽度让视线只落一次
2两个或三个次要指标,纵向排列或使用较窄区域天然更安静
3三种不同的图表形状并排展示,例如环形图、排名条形图和迷你图多样性传达出设计意图
4真正支持排序的表格,加上信息流或日志摘要之后再呈现细节
5用于结束页面的页脚行页面必须有明确的结束方式
使用带有明确跨度的 12 栏网格(
span 8
/
span 4
),然后依次折叠为 6 栏和 1 栏。绝不要在主要区带使用
repeat(auto-fit, …)
——它恰好会生成你要避免的等分卡片墙。

3. The chart inventory

3. 图表清单

All of these are plain inline SVG with
viewBox
, sized by CSS, filled from
--color-chart-*
. No chart library, no runtime dependency.
ChartGeometryUse it for
Bar / column
<rect>
per bucket,
rx
for a soft corner
Discrete periods
Candlestick
<line>
wick +
<rect>
body per period, class by up/down
OHLC price
VolumeBars under the price chart, same x-scale,
opacity:.45
Conviction behind a move
Moving average
<polyline>
over the candles, 2px, round joins
Trend through noise
Line / sparkline
<polyline>
,
pathLength="1"
for a draw animation
Trend in a cell
Area / stacked area
<path>
per band: forward along the top, reverse along the previous baseline, close
Composition over time
DepthTwo cumulative area paths mirrored around the midBook liquidity
WaterfallFloating
<rect>
per step + dashed connectors between levels
Attribution
Donut
<circle>
with
stroke-dasharray
and
rotate()
per segment
Share of a whole, 3-5 slices
Radial gaugeSame trick,
stroke-linecap:round
, 270-degree sweep
One value against a limit
Scatter / bubble
<circle>
, radius = third dimension
Two measures plus weight
Correlation matrixHTML table, cell tint via
color-mix
Pairwise relationships
HeatmapHTML table or
<rect>
grid, tint by value
Cohorts, calendars
Order bookHTML table with a depth bar per rowBids 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.
所有图表都使用带
viewBox
的纯内联 SVG,由 CSS 控制尺寸,并使用
--color-chart-*
填充。不依赖图表库或任何运行时依赖。
图表几何结构适用场景
条形图 / 柱状图每个分桶使用一个
<rect>
,通过
rx
实现柔和圆角
离散周期
K线图每个周期使用一条
<line>
影线和一个
<rect>
实体,并按上涨或下跌应用 class
OHLC 价格
成交量图价格图下方的柱形,使用相同的 x 轴刻度和
opacity:.45
反映价格变动背后的交易强度
移动平均线覆盖在 K 线上方的
<polyline>
,线宽 2px,使用圆角连接
从噪声中呈现趋势
折线图 / 迷你图
<polyline>
,使用
pathLength="1"
实现绘制动画
单元格内的趋势
面积图 / 堆叠面积图每个区带使用一个
<path>
:沿顶部正向绘制,沿上一条基线反向绘制,然后闭合
随时间变化的构成
深度图围绕中线镜像排列的两条累计面积路径订单簿流动性
瀑布图每个步骤使用一个浮动
<rect>
,并用虚线连接各个层级
归因分析
环形图使用
<circle>
,通过
stroke-dasharray
和逐段的
rotate()
绘制
整体占比,3 至 5 个分段
径向仪表盘使用相同方法,配合
stroke-linecap:round
,绘制 270 度扫描弧
单一数值与上限的对比
散点图 / 气泡图使用
<circle>
,半径表示第三个维度
两个度量及其权重
相关性矩阵HTML 表格,通过
color-mix
为单元格着色
两两关系
热力图HTML 表格或
<rect>
网格,根据数值为单元格着色
群组、日历
订单簿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
    role="img"
    plus either
    aria-label
    or
    <title>
    +
    <desc>
    referenced by
    aria-labelledby
    . Say what the chart shows, not that it is a chart: "Range 182.06 to 200.10, closing at 187.84" beats "price chart".
  • 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
    <caption>
    (use
    .sr-only
    when the panel header already says it),
    scope="col"
    /
    scope="row"
    , and
    aria-sort
    only if clicking really sorts.
  • Sortable headers, range tabs and theme toggles all declare state - so they must change it on a real click.
    verify_interactive.mjs
    clicks them and checks.
  • 每个 SVG 都要设置
    role="img"
    ,并提供
    aria-label
    ,或提供由
    aria-labelledby
    引用的
    <title>
    和
    <desc>
    。说明图表展示的内容,不要只说它是一个图表:“区间从 182.06 到 200.10,收于 187.84”优于“价格图表”。
  • 绝不能只依赖颜色传达含义。绿色搭配
    +
    和箭头,红色搭配
    -
    。在表格单元格中,上涨和下跌还应带有文字。
  • 表格需要
    <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
    --color-chart-4
    measured 2.65:1 in dark. Chart colours are tuned for large filled shapes.
  • 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:
    calc(var(--duration-fast) * 0.6 * n)
    , never a typed millisecond.
  • 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
    align-content: start
    on the field and an explicit
    block-size
    on the control. Measure the heights in the render - the difference is obvious in a screenshot and invisible in the markup.
  • 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 (
    grid-template-rows:auto minmax(0,1fr)
    , and that child's own tracks go
    minmax(<min>,1fr)
    so its rows grow too), or the rows share it out (
    align-content:space-between
    ), 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.
  • auto-fit
    silently drops a column, and no gate sees it.
    Three gauges in a panel about 340px wide with
    minmax(min(100%,7rem),1fr)
    resolved to two tracks and orphaned the third beside an empty cell. When the count is fixed and meaningful, write
    repeat(3,minmax(0,1fr))
    and give narrow widths their own rule.
  • 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
    aria-label
    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.
  • An
    .sr-only
    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.
  • A zero-area element that only has area while it animates reads as content lost under
    prefers-reduced-motion
    . Give a radar sweep a wedge, not a 1px line.
  • Never reuse a class name across layout and colour.
    .c4
    as both a four-column span and the fourth chart colour painted an entire panel pink.
以下每一项都曾出现在一个看起来已经完成的界面上。第一组问题由自动检查发现;标记为“no gate sees it”的问题,则是通过打开截图并亲眼查看发现的,因此这一步不可省略:
  • 图表调色板不是文本调色板。 深色模式下,
    --color-chart-4
    上的白色首字母对比度仅为 2.65:1。图表颜色针对大面积填充形状调校。
  • 凸起表面上的成功绿色文本对比度为 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
    ),或者给较矮的一列再增加一个面板。对这一行截图并检查每个面板的底边;这个问题在标记中永远不会显现。
  • auto-fit
    会悄悄丢弃一列,而且没有任何检查能够发现。在一个约 340px 宽的面板中放置三个仪表盘时,
    minmax(min(100%,7rem),1fr)
    会解析为两个轨道,导致第三个仪表盘与一个空单元格并排成为孤立项。当数量固定且具有实际意义时,应使用
    repeat(3,minmax(0,1fr))
    ,并为较窄宽度设置单独规则。
  • 分类图表必须把分类名称呈现在页面上,而且没有任何检查能够发现。一个展示五种缺陷类型的 Pareto 图,如果名称只存在于
    aria-label
    中,那么对所有看到它的人来说就只是一排匿名条形图。应把标签放在条形图下方,并在 viewBox 内部按等距布局绘图区,使匹配的标签网格无需第二套坐标系统即可对齐。
  • .sr-only
    需要一个已定位的祖先元素。否则,在滚动容器内,它会相对于初始包含块解析,落到视口之外,并使文档的滚动宽度增加数百像素。
  • 仅在动画期间才具有面积、静止时面积为零的元素,会让
    prefers-reduced-motion
    用户误以为内容丢失。雷达扫描应使用楔形区域,而不是 1px 的线条。
  • 绝不能在布局和颜色之间复用同一个 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:
${CLAUDE_SKILL_DIR}/../../../examples/showcase/index.html
(revenue console) and
${CLAUDE_SKILL_DIR}/../../../examples/terminal/index.html
(trading desk, ten chart types).
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>
然后在两种主题下,分别以 1600 和 390 的宽度截图并亲自查看。自动检查可能让绘制错误的图表通过。一个不对称的相关性矩阵会显示 16/16 全绿,却依然令人尴尬。
经过各项检查的实战参考:
${CLAUDE_SKILL_DIR}/../../../examples/showcase/index.html
(营收控制台)和
${CLAUDE_SKILL_DIR}/../../../examples/terminal/index.html
(交易台,包含十种图表类型)。