dashtaste 0.0.0-stage → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +124 -0
- package/dist/color.d.ts +4 -0
- package/dist/color.js +43 -0
- package/dist/engine.d.ts +11 -0
- package/dist/engine.js +39 -0
- package/dist/extract-in-page.d.ts +3 -0
- package/dist/extract-in-page.js +149 -0
- package/dist/extract.d.ts +3 -0
- package/dist/extract.js +39 -0
- package/dist/format.d.ts +18 -0
- package/dist/format.js +65 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/packs/cn.d.ts +2 -0
- package/dist/packs/cn.js +56 -0
- package/dist/packs/global.d.ts +2 -0
- package/dist/packs/global.js +45 -0
- package/dist/packs/index.d.ts +53 -0
- package/dist/packs/index.js +13 -0
- package/dist/rules/dt001-default-palette.d.ts +3 -0
- package/dist/rules/dt001-default-palette.js +11 -0
- package/dist/rules/dt002-rainbow-palette.d.ts +3 -0
- package/dist/rules/dt002-rainbow-palette.js +11 -0
- package/dist/rules/dt003-smooth-line.d.ts +3 -0
- package/dist/rules/dt003-smooth-line.js +9 -0
- package/dist/rules/dt004-symbols-everywhere.d.ts +3 -0
- package/dist/rules/dt004-symbols-everywhere.js +21 -0
- package/dist/rules/dt005-pie-slices.d.ts +3 -0
- package/dist/rules/dt005-pie-slices.js +13 -0
- package/dist/rules/dt006-pie-overuse.d.ts +3 -0
- package/dist/rules/dt006-pie-overuse.js +14 -0
- package/dist/rules/dt007-three-d.d.ts +3 -0
- package/dist/rules/dt007-three-d.js +16 -0
- package/dist/rules/dt008-dual-axis.d.ts +3 -0
- package/dist/rules/dt008-dual-axis.js +10 -0
- package/dist/rules/dt009-missing-unit.d.ts +3 -0
- package/dist/rules/dt009-missing-unit.js +8 -0
- package/dist/rules/dt010-bar-baseline.d.ts +3 -0
- package/dist/rules/dt010-bar-baseline.js +11 -0
- package/dist/rules/dt011-raw-large-numbers.d.ts +3 -0
- package/dist/rules/dt011-raw-large-numbers.js +21 -0
- package/dist/rules/dt012-unit-system.d.ts +3 -0
- package/dist/rules/dt012-unit-system.js +12 -0
- package/dist/rules/dt013-delta-convention.d.ts +3 -0
- package/dist/rules/dt013-delta-convention.js +21 -0
- package/dist/rules/dt014-delta-colour-only.d.ts +3 -0
- package/dist/rules/dt014-delta-colour-only.js +16 -0
- package/dist/rules/dt015-low-contrast-text.d.ts +3 -0
- package/dist/rules/dt015-low-contrast-text.js +28 -0
- package/dist/rules/dt016-thin-line-contrast.d.ts +3 -0
- package/dist/rules/dt016-thin-line-contrast.js +12 -0
- package/dist/rules/dt017-gradient-decoration.d.ts +3 -0
- package/dist/rules/dt017-gradient-decoration.js +15 -0
- package/dist/rules/dt018-glow.d.ts +3 -0
- package/dist/rules/dt018-glow.js +27 -0
- package/dist/rules/dt019-kpi-overload.d.ts +3 -0
- package/dist/rules/dt019-kpi-overload.js +7 -0
- package/dist/rules/dt020-kpi-rainbow.d.ts +3 -0
- package/dist/rules/dt020-kpi-rainbow.js +27 -0
- package/dist/rules/dt021-emoji-icons.d.ts +3 -0
- package/dist/rules/dt021-emoji-icons.js +10 -0
- package/dist/rules/dt022-cjk-min-size.d.ts +3 -0
- package/dist/rules/dt022-cjk-min-size.js +9 -0
- package/dist/rules/dt023-legend-single-series.d.ts +3 -0
- package/dist/rules/dt023-legend-single-series.js +8 -0
- package/dist/rules/dt024-bar-width.d.ts +1 -0
- package/dist/rules/dt024-bar-width.js +14 -0
- package/dist/rules/dt025-legend-not-direct-label.d.ts +1 -0
- package/dist/rules/dt025-legend-not-direct-label.js +11 -0
- package/dist/rules/dt026-line-weight.d.ts +1 -0
- package/dist/rules/dt026-line-weight.js +8 -0
- package/dist/rules/dt027-tabular-numerals.d.ts +1 -0
- package/dist/rules/dt027-tabular-numerals.js +16 -0
- package/dist/rules/dt028-hero-metric.d.ts +1 -0
- package/dist/rules/dt028-hero-metric.js +14 -0
- package/dist/rules/helpers.d.ts +32 -0
- package/dist/rules/helpers.js +161 -0
- package/dist/rules/index.d.ts +2 -0
- package/dist/rules/index.js +58 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.js +1 -0
- package/docs/rules.md +735 -0
- package/docs/usage.md +126 -0
- package/package.json +74 -4
- package/skills/dashtaste-cn/SKILL.md +51 -0
- package/skills/dashtaste-cn/references/avoid.md +135 -0
- package/skills/dashtaste-cn/references/charts.md +122 -0
- package/skills/dashtaste-cn/references/layout.md +78 -0
- package/skills/dashtaste-cn/references/numbers.md +93 -0
- package/skills/dashtaste-cn/references/tokens.md +72 -0
- package/skills/dashtaste-global/SKILL.md +43 -0
- package/skills/dashtaste-global/references/avoid.md +135 -0
- package/skills/dashtaste-global/references/charts.md +122 -0
- package/skills/dashtaste-global/references/layout.md +78 -0
- package/skills/dashtaste-global/references/numbers.md +83 -0
- package/skills/dashtaste-global/references/tokens.md +65 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Numbers and dates
|
|
2
|
+
|
|
3
|
+
## Compact amounts
|
|
4
|
+
|
|
5
|
+
Use 万 at 10,000 and 亿 at 100,000,000.
|
|
6
|
+
Use `1.23万`, with no internal space.
|
|
7
|
+
Fix a column to 万 when comparing rows or charts near a unit threshold.
|
|
8
|
+
For example, 9,800 and 12,300 become 0.98万 and 1.23万 in that column.
|
|
9
|
+
Use auto units for isolated KPIs with very different scales.
|
|
10
|
+
Auto examples: 12,300 → 1.23万; 230,000,000 → 2.3亿.
|
|
11
|
+
The formatter API uses auto units; fixed 万 is a local display calculation.
|
|
12
|
+
|
|
13
|
+
Use at most two decimals for Chinese compact units and one for global units.
|
|
14
|
+
Omit trailing zeroes on isolated compact amounts; use consistent decimals within a list or column.
|
|
15
|
+
Use `minimumFractionDigits: 2` for monetary lists and `compactFrom: 10000` for grouped full counts below 10,000.
|
|
16
|
+
Use integers for counts unless the measure is an average.
|
|
17
|
+
Use two decimals for monetary detail when required by the measure.
|
|
18
|
+
Use tabular numerals and right alignment for numeric columns.
|
|
19
|
+
Do not mix automatic unit switches within a shared chart axis.
|
|
20
|
+
Scale values before using a literal axis formatter; templates do not divide data.
|
|
21
|
+
A series value of 1.23 with axis name Orders (万) represents 12,300 orders.
|
|
22
|
+
|
|
23
|
+
## Percentages
|
|
24
|
+
|
|
25
|
+
Store rates as fractions in application data: 0.123 means 12.3%.
|
|
26
|
+
`formatPercent(0.123)` returns `12.3%`.
|
|
27
|
+
Use one decimal by default and zero for coarse whole-number shares.
|
|
28
|
+
Use two decimals only when changes at that scale matter.
|
|
29
|
+
Keep no space before `%`.
|
|
30
|
+
Distinguish a relative percent change from a percentage-point difference.
|
|
31
|
+
A move from 20% to 25% is +5 percentage points and +25% relative.
|
|
32
|
+
|
|
33
|
+
## Deltas
|
|
34
|
+
|
|
35
|
+
Compute (current − previous) / abs(previous).
|
|
36
|
+
Show ▲ for positive and ▼ for negative, always together with colour.
|
|
37
|
+
Zero is flat: `0.0%`, muted colour, no arrow.
|
|
38
|
+
Invalid values and a zero previous value display `–`.
|
|
39
|
+
Do not infer good or bad solely from direction; name the measure clearly.
|
|
40
|
+
Apply one page-wide delta convention, including tables and tooltips.
|
|
41
|
+
Default: red up, green down regardless of metric polarity, preserving the market
|
|
42
|
+
涨跌 convention. A deliberate green-up override must cover the page.
|
|
43
|
+
Set page `deltaColors: 'by-polarity'` (HTML `data-delta-colors="by-polarity"`)
|
|
44
|
+
to use green for improvement and red for deterioration. `polarity` defaults to
|
|
45
|
+
`higher-is-better`; `lower-is-better` makes rising churn, expenses, or refunds red
|
|
46
|
+
and falling values green. Arrows always follow the sign. Mark delta elements or
|
|
47
|
+
ancestors with `data-polarity="lower-is-better"` for extraction and DT013.
|
|
48
|
+
同比 compares the same period in the previous year.
|
|
49
|
+
环比 compares the immediately preceding period of the same length.
|
|
50
|
+
日环比 compares today with yesterday at the same elapsed cutoff.
|
|
51
|
+
周同比 compares with the same weekday of the previous week.
|
|
52
|
+
For incomplete periods compare equal elapsed durations, not full prior periods.
|
|
53
|
+
Label each comparison explicitly; never use a bare second percentage.
|
|
54
|
+
|
|
55
|
+
## Dates and shortcuts
|
|
56
|
+
|
|
57
|
+
Display dates as `2026-10-21`; use 24-hour times such as `14:30`.
|
|
58
|
+
Date shortcuts: 今天 / 昨天 / 近7天 / 近30天 / 本月 / 自定义。
|
|
59
|
+
Define 近7天 and 近30天 as inclusive calendar windows ending today.
|
|
60
|
+
本月 starts on day 1 and ends at the selected cutoff today.
|
|
61
|
+
今天 and 昨天 use the dashboard timezone, not the viewer's implicit timezone.
|
|
62
|
+
Use full-width punctuation in Chinese prose and spaces around Latin text or digits.
|
|
63
|
+
Keep compact values such as `1.23万` and percentages such as `12%` intact.
|
|
64
|
+
|
|
65
|
+
## Format API
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { formatCompact, formatPercent, formatDelta, formatDate } from 'dashtaste/format';
|
|
69
|
+
|
|
70
|
+
const amount = formatCompact(12300, 'cn');
|
|
71
|
+
const rate = formatPercent(0.123, 1);
|
|
72
|
+
const delta = formatDelta(110, 100, 'cn', { label: '环比' });
|
|
73
|
+
// Render delta.text and delta.color together; preserve the returned direction.
|
|
74
|
+
const date = formatDate(new Date(2026, 9, 21), 'cn');
|
|
75
|
+
const fixedWan = `${Number((12300 / 10000).toFixed(2))}万`;
|
|
76
|
+
const longDate = new Intl.DateTimeFormat('en-US', {
|
|
77
|
+
month: 'short',
|
|
78
|
+
day: 'numeric',
|
|
79
|
+
year: 'numeric',
|
|
80
|
+
}).format(new Date(2026, 9, 21));
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Set timezone handling before formatting server timestamps.
|
|
84
|
+
Never parse a display string back into analytical data.
|
|
85
|
+
Keep raw amounts, units, and comparison periods as separate fields.
|
|
86
|
+
|
|
87
|
+
## Numeral typography
|
|
88
|
+
|
|
89
|
+
Use "Instrument Sans" with "PingFang SC", "Noto Sans CJK SC", sans-serif fallback.
|
|
90
|
+
Set font-variant-numeric: tabular-nums on every number.
|
|
91
|
+
Keep decimal precision consistent within each metric and table column.
|
|
92
|
+
Use 500 for headings and values, 400 for body text; never exceed 600.
|
|
93
|
+
Use one hero at 2.2 times the secondary KPI size or larger.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Tokens
|
|
2
|
+
|
|
3
|
+
Ink and muted are text colours. Subtle and hairlines are decorative.
|
|
4
|
+
|
|
5
|
+
## light
|
|
6
|
+
|
|
7
|
+
| Token | Hex |
|
|
8
|
+
| ------------------- | ------- |
|
|
9
|
+
| light.page | #F2F4F2 |
|
|
10
|
+
| light.card | #FFFFFF |
|
|
11
|
+
| light.sunken | #F7F8F7 |
|
|
12
|
+
| light.ink | #141414 |
|
|
13
|
+
| light.muted | #636261 |
|
|
14
|
+
| light.subtle | #7B7B76 |
|
|
15
|
+
| light.hairline | #E6E6E6 |
|
|
16
|
+
| light.strong | #DDDDDD |
|
|
17
|
+
| light.primary | #141414 |
|
|
18
|
+
| light.brand | #3E6A88 |
|
|
19
|
+
| light.accent | #C68A1C |
|
|
20
|
+
| light.up | #C8372F |
|
|
21
|
+
| light.down | #167D4F |
|
|
22
|
+
| light.flat | #636261 |
|
|
23
|
+
| light.other | #BCBBBA |
|
|
24
|
+
| light.categorical.0 | #3E6A88 |
|
|
25
|
+
| light.categorical.1 | #20293A |
|
|
26
|
+
| light.categorical.2 | #8080F7 |
|
|
27
|
+
| light.categorical.3 | #B4A85D |
|
|
28
|
+
| light.categorical.4 | #77C4D6 |
|
|
29
|
+
| light.sequential.0 | #EEF2F5 |
|
|
30
|
+
| light.sequential.1 | #DDE4EA |
|
|
31
|
+
| light.sequential.2 | #B3CADB |
|
|
32
|
+
| light.sequential.3 | #74ABD0 |
|
|
33
|
+
| light.sequential.4 | #3E6A88 |
|
|
34
|
+
|
|
35
|
+
## dark
|
|
36
|
+
|
|
37
|
+
| Token | Hex |
|
|
38
|
+
| ------------------ | ------- |
|
|
39
|
+
| dark.bg | #121212 |
|
|
40
|
+
| dark.panel | #171716 |
|
|
41
|
+
| dark.sunken | #0A0B0A |
|
|
42
|
+
| dark.ink | #EEEEEB |
|
|
43
|
+
| dark.muted | #959590 |
|
|
44
|
+
| dark.subtle | #7B7B76 |
|
|
45
|
+
| dark.hairline | #2A2926 |
|
|
46
|
+
| dark.strong | #484843 |
|
|
47
|
+
| dark.brand | #74ABD0 |
|
|
48
|
+
| dark.accent | #E8B657 |
|
|
49
|
+
| dark.up | #DB655C |
|
|
50
|
+
| dark.down | #73B78E |
|
|
51
|
+
| dark.flat | #959590 |
|
|
52
|
+
| dark.other | #61615C |
|
|
53
|
+
| dark.categorical.0 | #74ABD0 |
|
|
54
|
+
| dark.categorical.1 | #E5B357 |
|
|
55
|
+
| dark.categorical.2 | #9B7EF0 |
|
|
56
|
+
| dark.categorical.3 | #466376 |
|
|
57
|
+
| dark.categorical.4 | #4B8C9C |
|
|
58
|
+
| dark.sequential.0 | #1F303B |
|
|
59
|
+
| dark.sequential.1 | #2A4456 |
|
|
60
|
+
| dark.sequential.2 | #3E6A88 |
|
|
61
|
+
| dark.sequential.3 | #74ABD0 |
|
|
62
|
+
| dark.sequential.4 | #B3CADB |
|
|
63
|
+
|
|
64
|
+
Use the numeral face with tabular figures. Headings use weight 500; body uses 400.
|
|
65
|
+
One hero anchors the page; all other numbers remain subordinate.
|
|
66
|
+
|
|
67
|
+
Use the mono face for Latin ticks and table headers: 11px, 0.06em tracking.
|
|
68
|
+
Keep CJK in the CJK face at 12px or larger, 16px on screens.
|
|
69
|
+
The accent token marks only the latest point of the main trend and sparkline end dots.
|
|
70
|
+
Its value label stays ink. The brand token supplies steel data strokes in light mode.
|
|
71
|
+
Red and green are reserved for deltas.
|
|
72
|
+
Paper and ink define the main surfaces and data strokes.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dashtaste-global
|
|
3
|
+
description: Build or review readable global-audience dashboards with concrete layout, chart, colour, and number defaults.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dashboard workflow
|
|
7
|
+
|
|
8
|
+
Use for dashboard pages, chart options, KPI strips, rankings, and dashboard reviews.
|
|
9
|
+
For a Chinese-market audience use dashtaste-cn.
|
|
10
|
+
|
|
11
|
+
1. Pick the global pack and light or dark mode before choosing colours.
|
|
12
|
+
2. Read [tokens](references/tokens.md) for exact colours and sizes.
|
|
13
|
+
3. Read [layout](references/layout.md) for page structure and controls.
|
|
14
|
+
4. Read [charts](references/charts.md) for the chart types you need.
|
|
15
|
+
5. Read [numbers](references/numbers.md) for units, dates, and comparisons.
|
|
16
|
+
6. Build the page with real data, explicit units, and clear hierarchy.
|
|
17
|
+
7. Run `npx dashtaste check options.json --pack global --max-warnings 0`.
|
|
18
|
+
For a rendered page, check its URL with a browser available through `CHROME_PATH`.
|
|
19
|
+
8. Fix errors and warnings; inspect informational findings. Recheck after edits.
|
|
20
|
+
Read [avoid](references/avoid.md) when replacing a flagged pattern.
|
|
21
|
+
|
|
22
|
+
## Ten rules to apply first
|
|
23
|
+
|
|
24
|
+
- DT001: Set explicit series colours from the selected pack.
|
|
25
|
+
- DT002: Keep at most five categorical colours; group the tail as Other.
|
|
26
|
+
- DT003: Draw straight line segments; smoothing invents intermediate values.
|
|
27
|
+
- DT004: Hide line symbols above 12 points.
|
|
28
|
+
- DT005: Use ranked bars for shares; no donuts in KPI boards.
|
|
29
|
+
- DT007: Use flat two-dimensional marks.
|
|
30
|
+
- DT009: Put units in value-axis names.
|
|
31
|
+
- DT010: Start bar value axes at zero and disable scale.
|
|
32
|
+
- DT013: Use green for improvement and red for deterioration; set lower-is-better polarity for churn and expenses.
|
|
33
|
+
- DT015: Meet 4.5:1 text contrast, or 3:1 for large text.
|
|
34
|
+
|
|
35
|
+
## Layout explains itself
|
|
36
|
+
|
|
37
|
+
Use no helper labels, explanatory captions, or “this chart shows” text.
|
|
38
|
+
Put units in axis names. Titles may state the finding, such as
|
|
39
|
+
“Returns fell for three weeks”. Labels identify data and controls directly.
|
|
40
|
+
Keep definitions in an accessible detail view when needed, outside chart captions.
|
|
41
|
+
|
|
42
|
+
Use one hero metric, one sheet, hairlines, and direct labels.
|
|
43
|
+
Use the measured defaults in the references for all KPI boards.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Patterns to avoid
|
|
2
|
+
|
|
3
|
+
Use this list when reviewing a page or replacing a flagged pattern.
|
|
4
|
+
Rule checks cover observable facts; inspect layout and copy manually as well.
|
|
5
|
+
|
|
6
|
+
## DT001: default-palette
|
|
7
|
+
|
|
8
|
+
Multiple series need explicit colours. Any default palette colour is flagged.
|
|
9
|
+
Replace it: set option.color to the pack palette (dashtaste tokens --pack <pack>).
|
|
10
|
+
|
|
11
|
+
## DT002: rainbow-palette
|
|
12
|
+
|
|
13
|
+
More than 6 distinct categorical colours or more than 5 saturated 60-degree hue buckets.
|
|
14
|
+
Replace it: use the pack palette and group remaining categories as Other.
|
|
15
|
+
|
|
16
|
+
## DT003: smooth-line
|
|
17
|
+
|
|
18
|
+
Line smoothing greater than zero draws values that do not exist.
|
|
19
|
+
Replace it: use straight segments: smooth: false.
|
|
20
|
+
|
|
21
|
+
## DT004: symbols-everywhere
|
|
22
|
+
|
|
23
|
+
Line symbols are noisy above 12 points; ECharts shows symbols by default.
|
|
24
|
+
Replace it: set showSymbol: false.
|
|
25
|
+
|
|
26
|
+
## DT005: pie-slices
|
|
27
|
+
|
|
28
|
+
Maximum 5 slices; cn rose charts allow 8.
|
|
29
|
+
Replace it: use horizontal bars or combine small parts into Other.
|
|
30
|
+
|
|
31
|
+
## DT006: pie-overuse
|
|
32
|
+
|
|
33
|
+
More than one pie per page or radius ratio above 0.75 warns. A global pie is informational.
|
|
34
|
+
Replace it: prefer horizontal bars; keep donut radius ratio at most 0.75.
|
|
35
|
+
|
|
36
|
+
## DT007: three-d
|
|
37
|
+
|
|
38
|
+
3D series, axes, coordinates, and pseudo-3D pie decoration distort comparisons.
|
|
39
|
+
Replace it: use flat 2D charts.
|
|
40
|
+
|
|
41
|
+
## DT008: dual-axis
|
|
42
|
+
|
|
43
|
+
Multiple value axes obscure comparisons, including mixed bar and line charts.
|
|
44
|
+
Replace it: use one value axis or aligned small multiples.
|
|
45
|
+
|
|
46
|
+
## DT009: missing-unit
|
|
47
|
+
|
|
48
|
+
Value axes need a name, formatter, unit metadata, or units in rendered ticks.
|
|
49
|
+
Replace it: put units in axis names, rendered ticks, or formatter metadata.
|
|
50
|
+
|
|
51
|
+
## DT010: bar-baseline
|
|
52
|
+
|
|
53
|
+
Bar value axes must start at zero; positive min and scale: true distort lengths.
|
|
54
|
+
Replace it: set min: 0 and scale: false.
|
|
55
|
+
|
|
56
|
+
## DT011: raw-large-numbers
|
|
57
|
+
|
|
58
|
+
At data maximum magnitude 10000 or above, axis, visible data label, and tooltip channels need formatters.
|
|
59
|
+
Replace it: format compact units: cn 万/亿; global K/M.
|
|
60
|
+
|
|
61
|
+
## DT012: unit-system
|
|
62
|
+
|
|
63
|
+
String formatter templates must use the selected compact unit system.
|
|
64
|
+
Replace it: use cn 万/亿 or global K/M/B consistently.
|
|
65
|
+
|
|
66
|
+
## DT013: delta-convention
|
|
67
|
+
|
|
68
|
+
Directional deltas must follow one page convention: global green-up; cn red-up by default.
|
|
69
|
+
Replace it: apply one deltaColors convention to the whole page.
|
|
70
|
+
|
|
71
|
+
## DT014: delta-colour-only
|
|
72
|
+
|
|
73
|
+
Directional colour must be accompanied by an arrow or signed number.
|
|
74
|
+
Replace it: add ▲/▼ or an explicit sign.
|
|
75
|
+
|
|
76
|
+
## DT015: low-contrast-text
|
|
77
|
+
|
|
78
|
+
Text needs 4.5:1; at least 24px or 18.66px bold needs 3:1. Chart label defaults use 4.5:1.
|
|
79
|
+
Replace it: increase text contrast against its background.
|
|
80
|
+
|
|
81
|
+
## DT016: thin-line-contrast
|
|
82
|
+
|
|
83
|
+
Line colours need at least 3:1 against the chart background.
|
|
84
|
+
Replace it: darken light-mode lines or lighten dark-mode lines.
|
|
85
|
+
|
|
86
|
+
## DT017: gradient-decoration
|
|
87
|
+
|
|
88
|
+
Card/page gradients and linear or radial chart fills add decoration.
|
|
89
|
+
Replace it: use solid backgrounds and fills.
|
|
90
|
+
|
|
91
|
+
## DT018: glow
|
|
92
|
+
|
|
93
|
+
Coloured CSS shadows with blur at least 12px, or chart shadowBlur at least 10, create glow.
|
|
94
|
+
Replace it: remove glow and use hairline borders.
|
|
95
|
+
|
|
96
|
+
## DT019: kpi-overload
|
|
97
|
+
|
|
98
|
+
More than 6 global or 8 cn KPI tiles weakens priority.
|
|
99
|
+
Replace it: keep only primary KPIs in the first view.
|
|
100
|
+
|
|
101
|
+
## DT020: kpi-rainbow
|
|
102
|
+
|
|
103
|
+
Three or more distinct accent colours on KPI values or tiles distract. Neutral greys and pack text/background tokens are excluded.
|
|
104
|
+
Replace it: use ink for values and reserve colour for deltas.
|
|
105
|
+
|
|
106
|
+
## DT021: emoji-icons
|
|
107
|
+
|
|
108
|
+
Emoji in headings, KPI labels, and rankings add inconsistent iconography.
|
|
109
|
+
Replace it: use plain text and plain numerals for rankings.
|
|
110
|
+
|
|
111
|
+
## DT022: cjk-min-size
|
|
112
|
+
|
|
113
|
+
CJK text must be at least 12px.
|
|
114
|
+
Replace it: set CJK text to at least 12px.
|
|
115
|
+
|
|
116
|
+
## DT023: legend-single-series
|
|
117
|
+
|
|
118
|
+
An explicitly visible legend on one series repeats context.
|
|
119
|
+
Replace it: hide the legend or label the series directly.
|
|
120
|
+
|
|
121
|
+
## Manual layout review
|
|
122
|
+
|
|
123
|
+
Helper labels and explanatory captions repeat visible structure; no automatic rule yet.
|
|
124
|
+
Decorative icon tiles distract from values; no automatic rule yet.
|
|
125
|
+
Repeated card boxes weaken the document hierarchy; no automatic rule yet.
|
|
126
|
+
|
|
127
|
+
## Measured anti-patterns
|
|
128
|
+
|
|
129
|
+
DT024: uncapped bars and bars wider than 24px (32px on screens).
|
|
130
|
+
DT025: legends for two to four lines without direct end labels.
|
|
131
|
+
DT026: decorative line strokes above 3px or below 1px.
|
|
132
|
+
DT027: proportional numerals in KPI values.
|
|
133
|
+
DT028: several equally sized KPIs without a clear hero.
|
|
134
|
+
Avoid donuts on KPI boards, dual axes, repeated boxed cards, and empty quadrants.
|
|
135
|
+
Avoid helper sentences, uppercase tracking, and in-flow shadows.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Chart defaults
|
|
2
|
+
|
|
3
|
+
These complete light-mode options use small values so no compact formatter is needed.
|
|
4
|
+
Copy an option into a JSON file and check with `--pack global`.
|
|
5
|
+
For dark mode replace all foreground and surface colours using tokens.md; check with `--mode dark`.
|
|
6
|
+
For large values, convert data to display units and name the unit in the axis.
|
|
7
|
+
Keep raw values separately for accessible detail views.
|
|
8
|
+
|
|
9
|
+
## Line
|
|
10
|
+
|
|
11
|
+
Use for change over time. Keep straight segments. Use filled 3–4px dots on series of at most 31 points. A 240px plot is a useful starting height.
|
|
12
|
+
|
|
13
|
+
<!-- prettier-ignore -->
|
|
14
|
+
```json
|
|
15
|
+
{"color": ["#1A1A18"], "xAxis": {"type": "category", "data": ["Mon", "Tue", "Wed"]}, "yAxis": {"type": "value", "name": "Orders"}, "series": [{"type": "line", "smooth": false, "showSymbol": true, "data": [12, 18, 16], "lineStyle": {"width": 1.5, "color": "#1A1A18"}, "symbol": "circle", "symbolSize": 4, "markPoint": {"symbol": "circle", "symbolSize": 7, "itemStyle": {"color": "#B65A08"}, "label": {"show": true, "position": "top", "formatter": "{c}"}, "data": [{"coord": [2, 16]}]}}]}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Bar
|
|
19
|
+
|
|
20
|
+
Compare amounts. Start at zero. Use horizontal bars for long category labels and at most 12px bar thickness on desktop.
|
|
21
|
+
|
|
22
|
+
<!-- prettier-ignore -->
|
|
23
|
+
```json
|
|
24
|
+
{"color": ["#1A1A18"], "xAxis": {"type": "value", "name": "Orders", "min": 0, "scale": false}, "yAxis": {"type": "category", "data": ["East", "West", "North"]}, "series": [{"type": "bar", "barMaxWidth": 12, "data": [24, 18, 12]}]}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Combo
|
|
28
|
+
|
|
29
|
+
Use aligned panels for different units. Keep comparison series on one shared axis.
|
|
30
|
+
|
|
31
|
+
<!-- prettier-ignore -->
|
|
32
|
+
```json
|
|
33
|
+
{"color": ["#1A1A18"], "xAxis": {"type": "category", "data": ["Mon", "Tue", "Wed"]}, "yAxis": {"type": "value", "name": "Orders", "min": 0}, "series": [{"name": "Orders", "type": "bar", "data": [24, 18, 12], "barMaxWidth": 12}, {"name": "Prior orders", "type": "line", "showSymbol": true, "smooth": false, "data": [12, 15, 18], "lineStyle": {"width": 1.5, "color": "#1A1A18"}, "symbol": "circle", "symbolSize": 4}]}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Share / pie / donut
|
|
37
|
+
|
|
38
|
+
No donuts or pies in KPI boards. Use a ranked bar list or a single 100% stacked bar with direct labels. The option below is for isolated composition analysis.
|
|
39
|
+
|
|
40
|
+
<!-- prettier-ignore -->
|
|
41
|
+
```json
|
|
42
|
+
{"color": ["#1A1A18"], "series": [{"type": "pie", "radius": ["35%", "60%"], "label": {"show": true, "formatter": "{b}: {d}%"}, "data": [{"name": "New", "value": 60}, {"name": "Repeat", "value": 40}]}]}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Funnel
|
|
46
|
+
|
|
47
|
+
Use for ordered process stages with a shared population. Keep one colour, descending values, and visible stage labels.
|
|
48
|
+
|
|
49
|
+
<!-- prettier-ignore -->
|
|
50
|
+
```json
|
|
51
|
+
{"color": ["#1A1A18"], "series": [{"type": "funnel", "sort": "descending", "label": {"show": true, "formatter": "{b}: {c}"}, "data": [{"name": "Started", "value": 90}, {"name": "Qualified", "value": 60}, {"name": "Completed", "value": 30}]}]}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Table
|
|
55
|
+
|
|
56
|
+
Use a semantic HTML table in production: left-align labels, right-align amounts, use 36px rows and hairline separators. This static ECharts graphic is a portable option example.
|
|
57
|
+
|
|
58
|
+
<!-- prettier-ignore -->
|
|
59
|
+
```json
|
|
60
|
+
{"graphic": [{"type": "text", "left": 16, "top": 16, "style": {"text": "Region Orders", "fill": "#1B1B18", "fontSize": 14}}, {"type": "text", "left": 16, "top": 52, "style": {"text": "East 24", "fill": "#1B1B18", "fontSize": 14}}]}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## KPI
|
|
64
|
+
|
|
65
|
+
Use real text with tabular figures. One 52–64px hero, 22–26px secondary values, 11px uppercase tracked mono labels for Latin, 13px CJK labels; weights 400 and 500.
|
|
66
|
+
|
|
67
|
+
<!-- prettier-ignore -->
|
|
68
|
+
```json
|
|
69
|
+
{"graphic": [{"type": "text", "left": 16, "top": 16, "style": {"text": "Orders", "fill": "#6B6B63", "fontSize": 14}}, {"type": "text", "left": 16, "top": 44, "style": {"text": "124", "fill": "#1B1B18", "fontSize": 32}}]}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Ranking / TOP N
|
|
73
|
+
|
|
74
|
+
Sort descending. Default to TOP 5; use TOP 10 only with room. Use muted tabular ranks without medals. Show the cutoff in the title.
|
|
75
|
+
|
|
76
|
+
<!-- prettier-ignore -->
|
|
77
|
+
```json
|
|
78
|
+
{"title": {"text": "Top 3 regions by orders"}, "color": ["#1A1A18"], "xAxis": {"type": "value", "name": "Orders", "min": 0}, "yAxis": {"type": "category", "inverse": true, "data": ["1 East", "2 West", "3 North"]}, "series": [{"type": "bar", "barMaxWidth": 12, "data": [24, 18, 12]}]}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Map
|
|
82
|
+
|
|
83
|
+
Use only for geographic questions, otherwise use ranking bars. Register a matching GeoJSON map as regions before setOption. Keep roam off and use a sequential scale with units.
|
|
84
|
+
|
|
85
|
+
<!-- prettier-ignore -->
|
|
86
|
+
```json
|
|
87
|
+
{"visualMap": {"min": 0, "max": 100, "text": ["Orders", "0"], "inRange": {"color": ["#1A1A18"]}}, "series": [{"type": "map", "map": "regions", "roam": false, "data": [{"name": "East", "value": 24}, {"name": "West", "value": 18}]}]}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Shared interaction defaults
|
|
91
|
+
|
|
92
|
+
Use tooltip trigger axis for time series and item for isolated marks.
|
|
93
|
+
Use one explicit colour for a single series; do not rely on theme defaults.
|
|
94
|
+
Hide the legend for one series. For comparisons, hide legends and use short annotations with thin 1px leader lines.
|
|
95
|
+
Do not use decorative gradients, shadows, 3D marks, or emoji in titles.
|
|
96
|
+
Keep missing observations missing; do not replace them with zero.
|
|
97
|
+
Use stable ordering for categories unless ranking is the question.
|
|
98
|
+
Keep controls outside the plotting rectangle.
|
|
99
|
+
Provide keyboard access and a table or textual data alternative.
|
|
100
|
+
Use a finding title only when the data supports it after filtering.
|
|
101
|
+
A unit belongs in the axis name, not in a helper caption.
|
|
102
|
+
|
|
103
|
+
## Measured defaults
|
|
104
|
+
|
|
105
|
+
Main lines use 1.5px ink; comparisons use 1px dashed mid-grey.
|
|
106
|
+
Long series hide symbols. Short series use small ink dots; comparisons or incomplete values use hollow dots.
|
|
107
|
+
Use straight segments, horizontal grid lines, and no y-axis line.
|
|
108
|
+
Bars use at most 65% of their category band; keep value labels outside.
|
|
109
|
+
Use one accent mark and neutral context; reserve red and green for deltas.
|
|
110
|
+
Small multiples use 1.5px lines without axes and a shared scale per row.
|
|
111
|
+
No area gradients, glow, or decorative heavy strokes.
|
|
112
|
+
|
|
113
|
+
Exactly one accent mark per chart: a filled 7px latest or peak dot and its value label.
|
|
114
|
+
Never use the accent on another chart element. Bars may highlight one bar instead.
|
|
115
|
+
Only latest and extreme values may have labels.
|
|
116
|
+
Use markLine, markPoint or graphic for leader-line annotations.
|
|
117
|
+
Thin ink bars are at most 12px; negative bars are mid-grey.
|
|
118
|
+
Inline table bars use ink at 20% opacity; the top row uses solid ink.
|
|
119
|
+
|
|
120
|
+
Use story-bearing data in examples. Annotate one event per chart with a leader line, a hollow ink dot, and a short label in empty space. Keep the latest point as the single accent.
|
|
121
|
+
|
|
122
|
+
Use one signature element per board. Place it alongside the main metric so it reinforces the data story.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Layout
|
|
2
|
+
|
|
3
|
+
Use one hero to establish the reading order.
|
|
4
|
+
The hero is 52–64px on desktop and 112–128px on a screen.
|
|
5
|
+
The hero is at least 2.2 times the next KPI.
|
|
6
|
+
Use weight 500 and letter spacing −0.02em for the hero.
|
|
7
|
+
Secondary KPIs use 22–26px, or 32–40px on screens.
|
|
8
|
+
Labels use 12–13px and weight 500.
|
|
9
|
+
Use sentence case without uppercase tracking.
|
|
10
|
+
Titles name the metric or state a supported finding.
|
|
11
|
+
Do not add helper text or explanatory sentences.
|
|
12
|
+
|
|
13
|
+
## Surface
|
|
14
|
+
|
|
15
|
+
The white page is the single surface.
|
|
16
|
+
Separate sections with hairlines and whitespace.
|
|
17
|
+
Avoid repeated boxed cards.
|
|
18
|
+
Inner radii are at most 6px.
|
|
19
|
+
Do not use in-flow shadows, gradients, glow, or glass effects.
|
|
20
|
+
Dark screens use hairlines rather than luminous panel borders.
|
|
21
|
+
|
|
22
|
+
## Density
|
|
23
|
+
|
|
24
|
+
Fill the viewport with relevant information.
|
|
25
|
+
Size the plot after reserving space for titles and direct labels.
|
|
26
|
+
Keep all content inside the viewport.
|
|
27
|
+
Use a main trend and a compact right rail.
|
|
28
|
+
Place categorical detail beneath the trend.
|
|
29
|
+
Keep date ranges in the header.
|
|
30
|
+
Align section headings and plot edges.
|
|
31
|
+
Align numeric baselines across the rail.
|
|
32
|
+
Reserve room for the longest label.
|
|
33
|
+
Avoid empty quadrants and decorative whitespace.
|
|
34
|
+
|
|
35
|
+
## Tables
|
|
36
|
+
|
|
37
|
+
Use semantic tables with 13px text and 36px rows.
|
|
38
|
+
Use 11px muted mono column headers for Latin; CJK headers stay at least 12px.
|
|
39
|
+
Right-align numbers with tabular figures.
|
|
40
|
+
Use hairline row separators.
|
|
41
|
+
Do not use zebra stripes or vertical rules.
|
|
42
|
+
Show share with a 4px inline bar.
|
|
43
|
+
The maximum share uses the accent; context uses a tint.
|
|
44
|
+
Use muted tabular ranks without medals.
|
|
45
|
+
Keep row names left aligned.
|
|
46
|
+
Show units consistently within a column.
|
|
47
|
+
Keep decimal precision consistent.
|
|
48
|
+
|
|
49
|
+
## Screen
|
|
50
|
+
|
|
51
|
+
Use a 1920×1080 viewport.
|
|
52
|
+
The minimum CJK size is 16px.
|
|
53
|
+
Use a 112–128px hero and a secondary KPI strip.
|
|
54
|
+
Use twelve regional small multiples instead of coloured tiles.
|
|
55
|
+
Use the same scale across regional sparklines.
|
|
56
|
+
Keep the current time visible in the header.
|
|
57
|
+
Mark the current hour with a vertical hairline.
|
|
58
|
+
Progress bars are 4px flat fills.
|
|
59
|
+
Use ink for the numerator and muted for the denominator.
|
|
60
|
+
|
|
61
|
+
## Checks
|
|
62
|
+
|
|
63
|
+
Check overflow at the exact target viewport.
|
|
64
|
+
Inspect every exported image for clipping and overlap.
|
|
65
|
+
Wait for local fonts before rendering.
|
|
66
|
+
Render at a device scale factor of two.
|
|
67
|
+
Keep tooltips out of the captured state.
|
|
68
|
+
Check contrast on every surface.
|
|
69
|
+
Keep at most three font weights, never above 600.
|
|
70
|
+
|
|
71
|
+
Header: a 20px, weight 500 title left and date range right.
|
|
72
|
+
Omit breadcrumbs, identity lines, helper lines and footer captions.
|
|
73
|
+
Use at most one hairline below the header.
|
|
74
|
+
Create breathing room with margins; avoid half-empty panels.
|
|
75
|
+
|
|
76
|
+
Use story-bearing data in examples. Annotate one event per chart with a leader line, a hollow ink dot, and a short label in empty space. Keep the latest point as the single accent.
|
|
77
|
+
|
|
78
|
+
Use one signature element per board. Place it alongside the main metric so it reinforces the data story.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Numbers and dates
|
|
2
|
+
|
|
3
|
+
## Compact amounts
|
|
4
|
+
|
|
5
|
+
Keep counts below 10,000 grouped in full. Use K from 10,000, M at 1,000,000, and B at 1,000,000,000.
|
|
6
|
+
Auto examples: 12,300 → 12.3K; 2,300,000 → 2.3M.
|
|
7
|
+
Fix one display unit across a comparison table or shared axis.
|
|
8
|
+
Keep exact values in details when compact rounding hides a meaningful difference.
|
|
9
|
+
The formatter API uses auto units; fixed units are a local display calculation.
|
|
10
|
+
|
|
11
|
+
Use at most two decimals for Chinese compact units and one for global units.
|
|
12
|
+
Omit trailing zeroes on isolated compact amounts; use consistent decimals within a list or column.
|
|
13
|
+
Use `minimumFractionDigits: 2` for monetary lists and `compactFrom: 10000` for grouped full counts below 10,000.
|
|
14
|
+
Use integers for counts unless the measure is an average.
|
|
15
|
+
Use two decimals for monetary detail when required by the measure.
|
|
16
|
+
Use tabular numerals and right alignment for numeric columns.
|
|
17
|
+
Do not mix automatic unit switches within a shared chart axis.
|
|
18
|
+
Scale values before using a literal axis formatter; templates do not divide data.
|
|
19
|
+
A series value of 1.23 with axis name Orders (万) represents 12,300 orders.
|
|
20
|
+
|
|
21
|
+
## Percentages
|
|
22
|
+
|
|
23
|
+
Store rates as fractions in application data: 0.123 means 12.3%.
|
|
24
|
+
`formatPercent(0.123)` returns `12.3%`.
|
|
25
|
+
Use one decimal by default and zero for coarse whole-number shares.
|
|
26
|
+
Use two decimals only when changes at that scale matter.
|
|
27
|
+
Keep no space before `%`.
|
|
28
|
+
Distinguish a relative percent change from a percentage-point difference.
|
|
29
|
+
A move from 20% to 25% is +5 percentage points and +25% relative.
|
|
30
|
+
|
|
31
|
+
## Deltas
|
|
32
|
+
|
|
33
|
+
Compute (current − previous) / abs(previous).
|
|
34
|
+
Show ▲ for positive and ▼ for negative, always together with colour.
|
|
35
|
+
Zero is flat: `0.0%`, muted colour, no arrow.
|
|
36
|
+
Invalid values and a zero previous value display `–`.
|
|
37
|
+
Do not infer good or bad solely from direction; name the measure clearly.
|
|
38
|
+
Apply one page-wide delta convention, including tables and tooltips.
|
|
39
|
+
Default: green for improvement, red for deterioration. `polarity` defaults to
|
|
40
|
+
`higher-is-better`; set `lower-is-better` for churn, expenses, and refunds.
|
|
41
|
+
Arrows always follow the sign; rising churn is red. Mark deltas or ancestors with
|
|
42
|
+
`data-polarity="lower-is-better"` for extraction and DT013.
|
|
43
|
+
Explicit red-up or green-up conventions are page-wide directional overrides.
|
|
44
|
+
Label comparisons as prior period or prior year, with equal time coverage.
|
|
45
|
+
For incomplete periods compare equal elapsed durations.
|
|
46
|
+
|
|
47
|
+
## Dates and shortcuts
|
|
48
|
+
|
|
49
|
+
Display dates as `Oct 21, 2026`; use a consistent dashboard timezone.
|
|
50
|
+
Use Today / Yesterday / Last 7 days / Last 30 days / This month / Custom.
|
|
51
|
+
Define rolling calendar windows inclusively and show the selected range.
|
|
52
|
+
`formatDate` currently returns `2026-10-21` for both packs.
|
|
53
|
+
Use the explicit presentation adapter below for a global long date.
|
|
54
|
+
|
|
55
|
+
## Format API
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { formatCompact, formatPercent, formatDelta, formatDate } from 'dashtaste/format';
|
|
59
|
+
|
|
60
|
+
const amount = formatCompact(12300, 'global');
|
|
61
|
+
const rate = formatPercent(0.123, 1);
|
|
62
|
+
const delta = formatDelta(110, 100, 'global', { label: 'Prior period' });
|
|
63
|
+
// Render delta.text and delta.color together; preserve the returned direction.
|
|
64
|
+
const date = formatDate(new Date(2026, 9, 21), 'global');
|
|
65
|
+
const fixedWan = `${Number((12300 / 10000).toFixed(2))}万`;
|
|
66
|
+
const longDate = new Intl.DateTimeFormat('en-US', {
|
|
67
|
+
month: 'short',
|
|
68
|
+
day: 'numeric',
|
|
69
|
+
year: 'numeric',
|
|
70
|
+
}).format(new Date(2026, 9, 21));
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Set timezone handling before formatting server timestamps.
|
|
74
|
+
Never parse a display string back into analytical data.
|
|
75
|
+
Keep raw amounts, units, and comparison periods as separate fields.
|
|
76
|
+
|
|
77
|
+
## Numeral typography
|
|
78
|
+
|
|
79
|
+
Use "Inter" with font-feature-settings "tnum", "cv11".
|
|
80
|
+
Set font-variant-numeric: tabular-nums on every number.
|
|
81
|
+
Keep decimal precision consistent within each metric and table column.
|
|
82
|
+
Use 500 for headings and values, 400 for body text; never exceed 600.
|
|
83
|
+
Use one hero at 2.2 times the secondary KPI size or larger.
|