@blueprint-chart/docs 0.1.18
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 +29 -0
- package/dist/api.d.ts +13 -0
- package/dist/api.js +29 -0
- package/dist/manifest.json +242 -0
- package/package.json +63 -0
- package/src/charts/area-stacked.md +64 -0
- package/src/charts/area.md +65 -0
- package/src/charts/bar-grouped.md +60 -0
- package/src/charts/bar-horizontal.md +71 -0
- package/src/charts/bar-multi.md +64 -0
- package/src/charts/bar-split.md +61 -0
- package/src/charts/bar-stacked.md +62 -0
- package/src/charts/bar-vertical.md +71 -0
- package/src/charts/column-stacked.md +57 -0
- package/src/charts/donut.md +66 -0
- package/src/charts/index.md +36 -0
- package/src/charts/line-multi.md +64 -0
- package/src/charts/line.md +65 -0
- package/src/charts/pie.md +63 -0
- package/src/guide/accessibility.md +196 -0
- package/src/guide/data-transforms.md +191 -0
- package/src/guide/dsl-editor.md +218 -0
- package/src/guide/embed.md +208 -0
- package/src/guide/getting-started.md +159 -0
- package/src/guide/palettes.md +207 -0
- package/src/guide/scenes.md +223 -0
- package/src/handbook/accessibility.md +109 -0
- package/src/handbook/annotations.md +143 -0
- package/src/handbook/anti-patterns.md +85 -0
- package/src/handbook/axes.md +116 -0
- package/src/handbook/choosing.md +120 -0
- package/src/handbook/color.md +141 -0
- package/src/handbook/design-principles.md +111 -0
- package/src/handbook/frame-elements.md +98 -0
- package/src/handbook/index.md +91 -0
- package/src/handbook/labels.md +117 -0
- package/src/handbook/tooltips.md +98 -0
- package/src/handbook/typography.md +93 -0
- package/src/reference/api/index.md +245 -0
- package/src/reference/dsl/annotations.md +135 -0
- package/src/reference/dsl/index.md +137 -0
- package/src/reference/dsl/properties.md +79 -0
- package/src/reference/dsl/scenes-and-transforms.md +97 -0
- package/src/reference/index.md +18 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Embedding Charts
|
|
2
|
+
|
|
3
|
+
Blueprint Chart is **static-first**: every chart is a self-contained artifact independent of any vendor server. There are three ways to put one on a page, and they all run entirely in the browser.
|
|
4
|
+
|
|
5
|
+
::: tip Data sovereignty
|
|
6
|
+
Charts render in-page (or in a sandboxed `srcdoc` iframe). Data never leaves the visitor's browser by default — no backend call, no analytics ping, no third-party SaaS. This is a structural property, not a marketing claim.
|
|
7
|
+
:::
|
|
8
|
+
|
|
9
|
+
## Option 1 — Drop in a `<script>` tag
|
|
10
|
+
|
|
11
|
+
The simplest path. Load the standalone runtime once per page, then add one `<script type="application/blueprint-chart">` per chart.
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<script src="https://unpkg.com/@blueprint-chart/lib/dist/lib/lib.iife.js"></script>
|
|
15
|
+
|
|
16
|
+
<script type="application/blueprint-chart">
|
|
17
|
+
chart line-multi {
|
|
18
|
+
title = "Wind and solar are catching up to hydroelectric power"
|
|
19
|
+
description = "Share of electricity generation by source (%)"
|
|
20
|
+
source = "IEA"
|
|
21
|
+
sourceUrl = "https://iea.org"
|
|
22
|
+
colors = "#59a14f, #edc949, #4e79a7"
|
|
23
|
+
legend = false
|
|
24
|
+
lineSymbols = true
|
|
25
|
+
lineSymbolShowOn = "last"
|
|
26
|
+
tooltips = true
|
|
27
|
+
|
|
28
|
+
data {
|
|
29
|
+
_series = "Hydro","Wind","Solar"
|
|
30
|
+
"2010" = 16.0,1.6,0.3
|
|
31
|
+
"2012" = 16.2,2.4,0.6
|
|
32
|
+
"2014" = 16.3,3.3,1.1
|
|
33
|
+
"2016" = 16.4,4.0,1.5
|
|
34
|
+
"2018" = 15.8,4.8,2.4
|
|
35
|
+
"2020" = 16.8,6.2,3.7
|
|
36
|
+
"2022" = 15.0,7.8,4.5
|
|
37
|
+
"2024" = 14.8,9.5,6.2
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
::: tip From the sample library
|
|
44
|
+
This is `packages/lib/src/samples/renewable-energy.bpc` — a multi-series line with explicit per-series colours and a single trailing symbol on the last datapoint of each series. Pasted verbatim into a page, it renders to a self-contained iframe with no extra wiring.
|
|
45
|
+
:::
|
|
46
|
+
|
|
47
|
+
The runtime auto-runs on `DOMContentLoaded`, finds every chart script tag, and replaces it with a sandboxed iframe (`sandbox="allow-scripts"`) sized via `postMessage` to match the rendered chart.
|
|
48
|
+
|
|
49
|
+
### Re-running after a dynamic insert
|
|
50
|
+
|
|
51
|
+
If you insert chart scripts after page load (SPA navigation, late-injected content) call the runtime explicitly:
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<script>
|
|
55
|
+
// Available globally as `BlueprintChart` when loaded via the IIFE bundle.
|
|
56
|
+
BlueprintChart.initBlueprint()
|
|
57
|
+
</script>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Option 2 — Embed export from the editor
|
|
61
|
+
|
|
62
|
+
The hosted editor at [blueprintchart.com](https://blueprintchart.com) ships an **Embed** export tab that produces a ready-to-paste snippet — runtime script tag + the chart source — that you can drop directly into any HTML page, CMS rich-text block, or newsletter template.
|
|
63
|
+
|
|
64
|
+
Choose **Embed** in the export panel and copy the snippet. Nothing else needs to be installed on the host page.
|
|
65
|
+
|
|
66
|
+
## Option 3 — Programmatic ESM API
|
|
67
|
+
|
|
68
|
+
For full control — server-side rendering, custom render passes, or wiring into your own component framework — use the ESM API directly.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import {
|
|
72
|
+
parse,
|
|
73
|
+
buildChartOptions,
|
|
74
|
+
parseData,
|
|
75
|
+
registerChart,
|
|
76
|
+
getChart,
|
|
77
|
+
} from '@blueprint-chart/lib'
|
|
78
|
+
|
|
79
|
+
const ast = parse(source) // BPC text → AST
|
|
80
|
+
const data = parseData(ast) // AST → ChartData
|
|
81
|
+
const options = buildChartOptions(ast) // AST → ChartOptions
|
|
82
|
+
|
|
83
|
+
const renderer = getChart(ast.chartType) // → ChartRenderer
|
|
84
|
+
renderer.render({ data, options, container })
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
See the [API reference](/reference/api/) for the full surface area, including frame/canvas/legend primitives and the chart-type registry.
|
|
88
|
+
|
|
89
|
+
## Static-site integrations
|
|
90
|
+
|
|
91
|
+
Each integration is a thin wrapper around the runtime script tag. Current status:
|
|
92
|
+
|
|
93
|
+
| Generator | Status | Notes |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| Plain HTML | ✅ Ships in `lib` | The `<script>` pattern above. |
|
|
96
|
+
| Hugo | ⏳ Planned | Phase 2 GTM deliverable. Shortcode wrapping the runtime. |
|
|
97
|
+
| Astro | ⏳ Planned | `<BlueprintChart>` Astro component. |
|
|
98
|
+
| Eleventy | ⏳ Planned | Shortcode + plugin. |
|
|
99
|
+
| Next.js | ⏳ Planned | React component wrapping the runtime in `useEffect`. |
|
|
100
|
+
|
|
101
|
+
If you need one of these now, the pattern is small enough to write inline: load the IIFE bundle once, then render a `<script type="application/blueprint-chart">` with the chart source in the body of your template.
|
|
102
|
+
|
|
103
|
+
## Self-hosting the runtime
|
|
104
|
+
|
|
105
|
+
The `unpkg.com` URL is convenient for prototyping; for production embeds, host the bundle yourself to avoid the third-party request and to pin a known version.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Copy the IIFE bundle into your site's static assets directory
|
|
109
|
+
cp node_modules/@blueprint-chart/lib/dist/lib/lib.iife.js public/vendor/
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<script src="/vendor/lib.iife.js"></script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Real-world embeds
|
|
117
|
+
|
|
118
|
+
Two end-to-end examples drawn straight from the lib's sample library — paste either snippet into an HTML page that already loads `lib.iife.js` and the runtime does the rest.
|
|
119
|
+
|
|
120
|
+
### Donut: share of energy by source
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<script type="application/blueprint-chart">
|
|
124
|
+
chart donut {
|
|
125
|
+
title = "Coal still generates a third of the world's electricity"
|
|
126
|
+
description = "Share by source, 2024"
|
|
127
|
+
source = "IEA"
|
|
128
|
+
sourceUrl = "https://iea.org"
|
|
129
|
+
colors = "#76b7b2, #4e79a7, #59a14f, #f28e2b, #edc949, #e15759, #b07aa1"
|
|
130
|
+
legendPosition = "right"
|
|
131
|
+
tooltips = true
|
|
132
|
+
displayAsPercentage = true
|
|
133
|
+
|
|
134
|
+
data {
|
|
135
|
+
"Coal" = 34.2
|
|
136
|
+
"Natural Gas" = 22.1
|
|
137
|
+
"Hydro" = 14.8
|
|
138
|
+
"Nuclear" = 9.4
|
|
139
|
+
"Wind" = 9.5
|
|
140
|
+
"Solar" = 6.2
|
|
141
|
+
"Other" = 3.8
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
</script>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
::: tip From the sample library
|
|
148
|
+
This is `packages/lib/src/samples/energy-sources.bpc` — a donut chart with an explicit categorical palette, right-anchored legend, and percentage display.
|
|
149
|
+
:::
|
|
150
|
+
|
|
151
|
+
### Line: a single-series time series with an annotation
|
|
152
|
+
|
|
153
|
+
```html
|
|
154
|
+
<script type="application/blueprint-chart">
|
|
155
|
+
chart line {
|
|
156
|
+
title = "US inflation peaked at 9.1% before retreating to near 3%"
|
|
157
|
+
description = "Consumer Price Index, year-over-year change (%)"
|
|
158
|
+
source = "Bureau of Labor Statistics"
|
|
159
|
+
sourceUrl = "https://bls.gov/cpi/"
|
|
160
|
+
colors = "#f28e2b"
|
|
161
|
+
lineSymbols = true
|
|
162
|
+
lineSymbolShape = "circle"
|
|
163
|
+
lineSymbolShowOn = "all"
|
|
164
|
+
verticalNumberFormat = ".1f"
|
|
165
|
+
tooltips = true
|
|
166
|
+
|
|
167
|
+
annotation "Jun 2022" {
|
|
168
|
+
text = "Peak: 9.1%"
|
|
169
|
+
dy = -12
|
|
170
|
+
showArrow = true
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
data {
|
|
174
|
+
"Jan 2021" = 1.4
|
|
175
|
+
"Jun 2021" = 5.4
|
|
176
|
+
"Jan 2022" = 7.5
|
|
177
|
+
"Jun 2022" = 9.1
|
|
178
|
+
"Jan 2023" = 6.4
|
|
179
|
+
"Jun 2023" = 3.0
|
|
180
|
+
"Jan 2024" = 3.1
|
|
181
|
+
"Jun 2024" = 3.0
|
|
182
|
+
"Jan 2025" = 3.0
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
</script>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
::: tip From the sample library
|
|
189
|
+
This is `packages/lib/src/samples/inflation-rate.bpc` — a single-series line with circular symbols on every datapoint, a pinned annotation on the peak, and a one-decimal vertical number format.
|
|
190
|
+
:::
|
|
191
|
+
|
|
192
|
+
## Security model
|
|
193
|
+
|
|
194
|
+
- The chart iframe uses `sandbox="allow-scripts"` only — no same-origin, no top-navigation, no forms.
|
|
195
|
+
- The chart source is inserted via `srcdoc` after HTML-entity escaping.
|
|
196
|
+
- The runtime does no network requests for rendering. All chart logic runs locally.
|
|
197
|
+
- The parent page communicates with the iframe only via a single `postMessage` channel used to resize the iframe to fit content.
|
|
198
|
+
|
|
199
|
+
## Troubleshooting
|
|
200
|
+
|
|
201
|
+
**The chart doesn't appear.**
|
|
202
|
+
Check the browser console for parse errors. The runtime keeps the original DSL visible inside a `.blueprint-chart-placeholder` div if rendering fails, so the source remains diff-able.
|
|
203
|
+
|
|
204
|
+
**The iframe height doesn't match the chart.**
|
|
205
|
+
The runtime listens for `blueprint-chart-resize` messages and resizes accordingly. A Content Security Policy that blocks inline scripts inside iframes will break this — the `srcdoc` iframe needs `script-src 'unsafe-inline'` or a matching `'sha256-…'` directive.
|
|
206
|
+
|
|
207
|
+
**My CMS strips `<script>` tags.**
|
|
208
|
+
Use the editor's standalone HTML export instead and host it as a static asset.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
Blueprint Chart is published as three packages on NPM. Pick the one that matches what you're building.
|
|
4
|
+
|
|
5
|
+
<table>
|
|
6
|
+
<thead><tr><th>Package</th><th>When to use it</th></tr></thead>
|
|
7
|
+
<tbody>
|
|
8
|
+
<tr><td nowrap><a href="https://www.npmjs.com/package/@blueprint-chart/lib"><code>@blueprint-chart/lib</code></a></td><td>Pure TypeScript chart engine — render charts from data + options or from a <code>.bpc</code> source. No Vue.</td></tr>
|
|
9
|
+
<tr><td nowrap><a href="https://www.npmjs.com/package/@blueprint-chart/ui"><code>@blueprint-chart/ui</code></a></td><td>Vue 3 component library — forms, panels, navigation, scene timeline, layout primitives.</td></tr>
|
|
10
|
+
<tr><td nowrap><a href="https://www.npmjs.com/package/@blueprint-chart/editor"><code>@blueprint-chart/editor</code></a></td><td>The full SPA — runs on top of <code>lib</code> + <code>ui</code>. Deployed at <a href="https://blueprintchart.com">blueprintchart.com</a>.</td></tr>
|
|
11
|
+
</tbody>
|
|
12
|
+
</table>
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
::: code-group
|
|
17
|
+
|
|
18
|
+
```bash [pnpm]
|
|
19
|
+
pnpm add @blueprint-chart/lib
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash [npm]
|
|
23
|
+
npm install @blueprint-chart/lib
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```bash [yarn]
|
|
27
|
+
yarn add @blueprint-chart/lib
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
:::
|
|
31
|
+
|
|
32
|
+
## Render a chart from a BPC source
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { parse, buildChartOptions, parseData } from '@blueprint-chart/lib'
|
|
36
|
+
|
|
37
|
+
const source = `
|
|
38
|
+
chart line {
|
|
39
|
+
title = "Bitcoin surged past $90,000 in 2024"
|
|
40
|
+
description = "USD, year-end closing price"
|
|
41
|
+
source = "CoinGecko"
|
|
42
|
+
sourceUrl = "https://www.coingecko.com"
|
|
43
|
+
colors = "#f7931a"
|
|
44
|
+
lineSymbols = true
|
|
45
|
+
lineSymbolShowOn = "all"
|
|
46
|
+
lineSymbolShape = "diamond"
|
|
47
|
+
verticalNumberFormat = ",.0f"
|
|
48
|
+
tooltips = true
|
|
49
|
+
|
|
50
|
+
annotation "2021" {
|
|
51
|
+
text = "All-time high cycle"
|
|
52
|
+
dy = -12
|
|
53
|
+
showArrow = true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
data {
|
|
57
|
+
"2016" = 963
|
|
58
|
+
"2017" = 13880
|
|
59
|
+
"2018" = 3742
|
|
60
|
+
"2019" = 7194
|
|
61
|
+
"2020" = 28949
|
|
62
|
+
"2021" = 46306
|
|
63
|
+
"2022" = 16547
|
|
64
|
+
"2023" = 42258
|
|
65
|
+
"2024" = 93429
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
`
|
|
69
|
+
|
|
70
|
+
const ast = parse(source)
|
|
71
|
+
const data = parseData(ast)
|
|
72
|
+
const options = buildChartOptions(ast)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
::: tip From the sample library
|
|
76
|
+
This is `packages/lib/src/samples/bitcoin-price.bpc` — a single-series line chart with a fixed-colour brand override (`colors = "#f7931a"`), diamond symbols on every datapoint, and a pinned annotation marking the 2021 peak.
|
|
77
|
+
:::
|
|
78
|
+
|
|
79
|
+
From here you wire the `data` and `options` into the renderer of your choice — `@blueprint-chart/lib` exposes the building blocks (`createFrame`, `createCanvas`, `renderLegend`, `renderHorizontalAxis`, `renderVerticalAxis`) plus a chart-type registry (`registerChart` / `getChart`). See [the API reference](/reference/api/).
|
|
80
|
+
|
|
81
|
+
## Drop a chart into any page
|
|
82
|
+
|
|
83
|
+
If you don't need the programmatic API, use the bundled runtime. It picks up every `<script type="application/blueprint-chart">` tag and replaces it with a sandboxed iframe containing the rendered chart.
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<script src="https://unpkg.com/@blueprint-chart/lib/dist/runtime.iife.js"></script>
|
|
87
|
+
|
|
88
|
+
<script type="application/blueprint-chart">
|
|
89
|
+
chart donut {
|
|
90
|
+
title = "Coal still generates a third of the world's electricity"
|
|
91
|
+
description = "Share by source, 2024"
|
|
92
|
+
source = "IEA"
|
|
93
|
+
sourceUrl = "https://iea.org"
|
|
94
|
+
colors = "#76b7b2, #4e79a7, #59a14f, #f28e2b, #edc949, #e15759, #b07aa1"
|
|
95
|
+
legendPosition = "right"
|
|
96
|
+
tooltips = true
|
|
97
|
+
displayAsPercentage = true
|
|
98
|
+
|
|
99
|
+
data {
|
|
100
|
+
"Coal" = 34.2
|
|
101
|
+
"Natural Gas" = 22.1
|
|
102
|
+
"Hydro" = 14.8
|
|
103
|
+
"Nuclear" = 9.4
|
|
104
|
+
"Wind" = 9.5
|
|
105
|
+
"Solar" = 6.2
|
|
106
|
+
"Other" = 3.8
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
</script>
|
|
110
|
+
|
|
111
|
+
<script>
|
|
112
|
+
blueprintChart.initBlueprint()
|
|
113
|
+
</script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
::: tip From the sample library
|
|
117
|
+
This is `packages/lib/src/samples/energy-sources.bpc` — a donut chart with a hand-picked categorical palette, percentage display, and a right-anchored legend.
|
|
118
|
+
:::
|
|
119
|
+
|
|
120
|
+
See the [embedding guide](/guide/embed) for static sites, CMS integrations, and the base64 iframe pattern.
|
|
121
|
+
|
|
122
|
+
## Try the editor instead
|
|
123
|
+
|
|
124
|
+
The fastest way to author a chart is in the hosted editor.
|
|
125
|
+
|
|
126
|
+
- Open <https://blueprintchart.com>
|
|
127
|
+
- Pick a sample or paste your own CSV / data
|
|
128
|
+
- Tweak in the panel, watch the live preview, then export as a standalone HTML file or an embeddable `<script>` tag
|
|
129
|
+
|
|
130
|
+
The editor runs entirely in your browser — no account, no server upload, no telemetry.
|
|
131
|
+
|
|
132
|
+
## Build from source
|
|
133
|
+
|
|
134
|
+
If you want to contribute or develop against an unreleased build, see the [repository README](https://github.com/blueprint-chart/blueprint-chart#readme) and `AGENTS.md` for canonical conventions.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git clone git@github.com:blueprint-chart/blueprint-chart.git
|
|
138
|
+
cd blueprint-chart
|
|
139
|
+
make install
|
|
140
|
+
make dev # editor at http://localhost:5555
|
|
141
|
+
make dev-docs # these docs at http://localhost:4445
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Try these samples
|
|
145
|
+
|
|
146
|
+
The lib ships ~40 ready-to-run `.bpc` files under `packages/lib/src/samples/`. They double as canonical examples and as integration-test fixtures. A handful worth opening first:
|
|
147
|
+
|
|
148
|
+
- `bitcoin-price.bpc` — single-series line with a brand colour, year-by-year diamond symbols, and an annotation on the 2021 peak.
|
|
149
|
+
- `co2-emissions-story.bpc` — a bar chart with three scenes, each highlighting a different country to walk a reader through the same data.
|
|
150
|
+
- `farm-compass.bpc` — a multi-scene narrative where later scenes swap the chart type (area → line → area-stacked) without rewriting the source.
|
|
151
|
+
- `browser-market.bpc` — a donut driven by the named `Heep` palette, with right-anchored legend and percentage display.
|
|
152
|
+
- `medal-count.bpc` — `bar-multi` with a gold / silver / bronze custom palette, sorted descending, top-anchored legend.
|
|
153
|
+
- `temperature-anomaly.bpc` — single-series line tuned for dark mode (`autoContrast = false`, `allowDarkMode = true`) with a curved annotation calling out the 2015 Paris Agreement.
|
|
154
|
+
|
|
155
|
+
## Next steps
|
|
156
|
+
|
|
157
|
+
- [BPC DSL specification](/reference/dsl/) — the full language reference.
|
|
158
|
+
- [Embedding charts](/guide/embed) — embed flows, CMS integrations, runtime details.
|
|
159
|
+
- [API reference](/reference/api/) — every exported symbol from `@blueprint-chart/lib`.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Palettes
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Palettes
|
|
6
|
+
|
|
7
|
+
> 50+ curated categorical palettes, plus the helpers to resolve, audit, and adjust them for the background you render against.
|
|
8
|
+
|
|
9
|
+
## Why this matters
|
|
10
|
+
|
|
11
|
+
Color is the second most powerful encoding after position — and the easiest to misuse. Blueprint Chart ships a curated catalogue of palettes (sourced from [pypalettes](https://github.com/y-sunflower/pypalettes), MIT) so chart authors can pick a tested set instead of hand-rolling one. Each palette is perceptually balanced enough to read at small sizes; the accompanying helpers let you contrast-check and CVD-check before publishing.
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
Pick a palette by name in a `.bpc` document:
|
|
16
|
+
|
|
17
|
+
```bpc
|
|
18
|
+
chart donut {
|
|
19
|
+
title = "Chrome dominates with two-thirds of the desktop browser market"
|
|
20
|
+
description = "Worldwide, January 2025"
|
|
21
|
+
source = "StatCounter"
|
|
22
|
+
sourceUrl = "https://gs.statcounter.com"
|
|
23
|
+
colorPalette = "Heep"
|
|
24
|
+
legendPosition = "right"
|
|
25
|
+
tooltips = true
|
|
26
|
+
displayAsPercentage = true
|
|
27
|
+
|
|
28
|
+
data {
|
|
29
|
+
"Chrome" = 65.7
|
|
30
|
+
"Edge" = 13.1
|
|
31
|
+
"Safari" = 8.9
|
|
32
|
+
"Firefox" = 6.3
|
|
33
|
+
"Opera" = 3.1
|
|
34
|
+
"Others" = 2.9
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
::: tip From the sample library
|
|
40
|
+
This is `packages/lib/src/samples/browser-market.bpc` — a donut chart driven entirely by the named `Heep` palette. Each slice picks up the next colour from the resolved palette array.
|
|
41
|
+
:::
|
|
42
|
+
|
|
43
|
+
Or pull the colours into TypeScript:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { resolvePalette, listPalettes } from '@blueprint-chart/lib'
|
|
47
|
+
|
|
48
|
+
resolvePalette('Egypt')
|
|
49
|
+
// → ['#dd5129', '#0f7ba2', '#43b284', '#fab255']
|
|
50
|
+
|
|
51
|
+
listPalettes()
|
|
52
|
+
// → PaletteEntry[] with every palette currently registered
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`resolvePalette()` returns a mutable copy of the underlying readonly array, so you can safely shuffle, slice, or reorder.
|
|
56
|
+
|
|
57
|
+
## How it works
|
|
58
|
+
|
|
59
|
+
Palettes are pure data — `packages/lib/src/charts/palettes.ts` declares a `PALETTES` array of `{ name, label, colors }` entries, indexed into a `PALETTE_MAP` for O(1) lookup. At render time:
|
|
60
|
+
|
|
61
|
+
1. The chart's `colorPalette` property (a palette `name`) is resolved by `resolvePalette()` into an array of hex strings.
|
|
62
|
+
2. Each series is mapped to a palette entry by `resolveSeriesColor`. Per-series overrides — `colors`, `series { color = … }`, `colorize "<name>"` — take precedence.
|
|
63
|
+
3. When `autoContrast = true`, `adjustColorsForBackground(colors, bg)` nudges the lightness of each colour until every series clears WCAG AA against the frame background **and** every adjacent pair has at least CIE2000 ΔE ≥ 12. Hue and saturation are preserved.
|
|
64
|
+
|
|
65
|
+
The library uses [chroma-js](https://gka.github.io/chroma.js/) under the hood for parsing, deltaE, and perceptual interpolation. See the [color handbook](/handbook/color) for the underlying theory (sequential vs. diverging vs. categorical, the perceptual-uniformity trap, ten ways to use less colour).
|
|
66
|
+
|
|
67
|
+
## Recipes
|
|
68
|
+
|
|
69
|
+
### Use a hand-picked colour
|
|
70
|
+
|
|
71
|
+
The `colorPalette` property accepts any registered palette `name`. For a one-off brand-coloured chart, drop `colors = "<hex>"` (single value) and skip the palette entirely:
|
|
72
|
+
|
|
73
|
+
```bpc
|
|
74
|
+
chart line {
|
|
75
|
+
title = "Bitcoin surged past $90,000 in 2024"
|
|
76
|
+
description = "USD, year-end closing price"
|
|
77
|
+
source = "CoinGecko"
|
|
78
|
+
colors = "#f7931a"
|
|
79
|
+
lineSymbols = true
|
|
80
|
+
lineSymbolShowOn = "all"
|
|
81
|
+
lineSymbolShape = "diamond"
|
|
82
|
+
|
|
83
|
+
data {
|
|
84
|
+
"2016" = 963
|
|
85
|
+
"2020" = 28949
|
|
86
|
+
"2022" = 16547
|
|
87
|
+
"2024" = 93429
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
::: tip From the sample library
|
|
93
|
+
This is `packages/lib/src/samples/bitcoin-price.bpc` — Bitcoin orange (`#f7931a`) hard-coded as the single series colour, so the chart matches the brand regardless of the active palette.
|
|
94
|
+
:::
|
|
95
|
+
|
|
96
|
+
For multi-series charts, pass a comma-separated list (`colors = "#a","#b","#c"`) — `medal-count.bpc` does exactly this with gold, silver, and bronze for the Olympic ranking.
|
|
97
|
+
|
|
98
|
+
### Override a single category
|
|
99
|
+
|
|
100
|
+
`colorize "<name>"` re-paints one entry without disturbing the rest of the palette. `letter-frequency.bpc` uses it to make the winning entry pop in red against the named `London` palette:
|
|
101
|
+
|
|
102
|
+
```bpc
|
|
103
|
+
chart bar-vertical {
|
|
104
|
+
title = "E is the most frequent letter in English"
|
|
105
|
+
description = "How often each letter appears in typical English text"
|
|
106
|
+
colorPalette = "London"
|
|
107
|
+
sort = descending
|
|
108
|
+
valueLabels = true
|
|
109
|
+
|
|
110
|
+
colorize "E" {
|
|
111
|
+
color = "#e15759"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
data {
|
|
115
|
+
"E" = 12.70
|
|
116
|
+
"T" = 9.06
|
|
117
|
+
"A" = 8.17
|
|
118
|
+
"O" = 7.51
|
|
119
|
+
"I" = 6.97
|
|
120
|
+
"N" = 6.75
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
::: tip From the sample library
|
|
126
|
+
This is `packages/lib/src/samples/letter-frequency.bpc` — every other bar takes its colour from `London`; only `E` is overridden, drawing the eye to the headline finding.
|
|
127
|
+
:::
|
|
128
|
+
|
|
129
|
+
### Auto-tune the palette to the frame background
|
|
130
|
+
|
|
131
|
+
Opt a chart into automatic contrast adjustment by setting `autoContrast = true`. The renderer reads the effective background colour through `resolveBackgroundColor(container)` and nudges each palette entry until WCAG AA and a minimum perceptual distance are both satisfied — useful when the same chart ships in both light and dark themes.
|
|
132
|
+
|
|
133
|
+
### Audit a palette before shipping
|
|
134
|
+
|
|
135
|
+
The contrast and CVD helpers run outside any chart instance, which makes them handy for build-time linting:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import {
|
|
139
|
+
resolvePalette,
|
|
140
|
+
wcagContrastRatio,
|
|
141
|
+
wcagLevel,
|
|
142
|
+
checkCvdColors,
|
|
143
|
+
} from '@blueprint-chart/lib'
|
|
144
|
+
|
|
145
|
+
const palette = resolvePalette('Egypt')!
|
|
146
|
+
const bg = '#ffffff'
|
|
147
|
+
|
|
148
|
+
for (const color of palette) {
|
|
149
|
+
const ratio = wcagContrastRatio(color, bg)
|
|
150
|
+
console.log(color, ratio.toFixed(2), wcagLevel(ratio))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const issues = checkCvdColors(palette)
|
|
154
|
+
// issues[].pairs lists colours that collapse under each dichromacy
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
See [Accessibility](/guide/accessibility) for the full audit workflow.
|
|
158
|
+
|
|
159
|
+
### Browse the catalogue at runtime
|
|
160
|
+
|
|
161
|
+
`listPalettes()` returns every entry currently registered, including its human-readable `label`. Drop it into a picker, a Histoire story, or a unit test:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { listPalettes } from '@blueprint-chart/lib'
|
|
165
|
+
|
|
166
|
+
const options = listPalettes().map((p) => ({
|
|
167
|
+
value: p.name,
|
|
168
|
+
label: p.label,
|
|
169
|
+
swatch: p.colors,
|
|
170
|
+
}))
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
A small sampling of the catalogue (run `listPalettes()` for the current full list):
|
|
174
|
+
|
|
175
|
+
| name | label | colours |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `Blueprint` | Blueprint | 6 |
|
|
178
|
+
| `JosefAlbers` | Albers | 5 |
|
|
179
|
+
| `Egypt` | Egypt | 4 |
|
|
180
|
+
| `Klimt` | Klimt | 6 |
|
|
181
|
+
| `Maya` | Maya | 5 |
|
|
182
|
+
| `Sunset` | Sunset | 7 |
|
|
183
|
+
| `TheovanDoesburg` | Van Doesburg | 5 |
|
|
184
|
+
|
|
185
|
+
## API surface
|
|
186
|
+
|
|
187
|
+
Exported from `@blueprint-chart/lib`:
|
|
188
|
+
|
|
189
|
+
| Symbol | One-liner |
|
|
190
|
+
| --- | --- |
|
|
191
|
+
| `resolvePalette(name)` | Returns a mutable `string[]` of hex colours for a palette name, or `undefined`. |
|
|
192
|
+
| `listPalettes()` | Returns every `PaletteEntry` currently registered. |
|
|
193
|
+
| `PaletteEntry` (type) | `{ name: string, label: string, colors: readonly string[] }`. |
|
|
194
|
+
| `resolveSeriesColor(...)` | Resolves a series to its final colour, respecting overrides. |
|
|
195
|
+
| `resolveSeriesInterpolation(...)` | Resolves the interpolation function for a series (line / area charts). |
|
|
196
|
+
| `isSeriesHidden(...)` | Whether a series is hidden by a scene or override. |
|
|
197
|
+
| `resolveBackgroundColor(el)` | Walks ancestors until it finds a non-transparent background. |
|
|
198
|
+
| `adjustColorsForBackground(colors, bg)` | Returns a legibility-tuned copy of the palette for the given background. |
|
|
199
|
+
|
|
200
|
+
For the accessibility helpers (`wcagContrastRatio`, `wcagLevel`, `checkCvdColors`, …) see the [Accessibility guide](/guide/accessibility).
|
|
201
|
+
|
|
202
|
+
## See also
|
|
203
|
+
|
|
204
|
+
- [Accessibility](/guide/accessibility) — WCAG and CVD utilities.
|
|
205
|
+
- [Colour handbook](/handbook/color) — palette theory and reduction techniques.
|
|
206
|
+
- [BPC DSL — Color directives](/reference/dsl/annotations#color-directives) for `colorize`, `highlight`, `areafill`.
|
|
207
|
+
- [API reference](/reference/api/#palettes) for the full export list.
|