diff --git a/docs/engineering/skills/chart-standards.md b/docs/engineering/skills/chart-standards.md index bda6ac1b7..aacb75ac7 100644 --- a/docs/engineering/skills/chart-standards.md +++ b/docs/engineering/skills/chart-standards.md @@ -5,7 +5,8 @@ This skill ensures consistent chart styling across PolicyEngine visualizations. ## Chart libraries - **Recharts** (default) — used for all standard charts (bar, line, area, stacked bar) -- **Plotly** (exceptions only) — choropleth maps, hexagonal maps, waterfall charts, blog/notebook embedded JSON +- **Plotly** (exceptions only) — choropleth maps, hexagonal maps, waterfall charts, notebook embedded JSON, and legacy blog posts +- **Blog posts on policyengine.org** — ` ```chart ` blocks, rendered by the website with the ui-kit chart defaults (see [Blog post charts](#blog-post-charts)) ## Recharts chart pattern @@ -210,14 +211,14 @@ const description = ( These charts remain on Plotly (`react-plotly.js`): -| Chart | Reason | -| ------------------------------------- | ---------------------------------------------- | -| `USDistrictChoroplethMap.tsx` | No Recharts geo support | -| `HexagonalMap.tsx` | Custom scatter with hex markers | -| `BudgetaryImpactSubPage.tsx` | Waterfall chart (no native Recharts waterfall) | -| `BudgetaryImpactByProgramSubPage.tsx` | Waterfall chart | -| `MarkdownFormatter.tsx` | Blog posts embed native Plotly JSON | -| `NotebookRenderer.tsx` | Notebooks embed native Plotly JSON | +| Chart | Reason | +| --------------------------------------------------- | ------------------------------------------------------------------------ | +| `USDistrictChoroplethMap.tsx` | No Recharts geo support | +| `HexagonalMap.tsx` | Custom scatter with hex markers | +| `BudgetaryImpactSubPage.tsx` | Waterfall chart (no native Recharts waterfall) | +| `BudgetaryImpactByProgramSubPage.tsx` | Waterfall chart | +| `website/src/components/blog/MarkdownFormatter.tsx` | Legacy posts embed native Plotly JSON; new posts use ` ```chart ` blocks | +| `NotebookRenderer.tsx` | Notebooks embed native Plotly JSON | For these files, continue using the Plotly patterns: @@ -237,6 +238,33 @@ import { />; ``` +## Blog post charts + +Posts draw charts as ` ```chart ` fenced blocks holding a JSON spec. +`website/src/components/blog/BlogChart.tsx` parses each block and wraps it in a figure with +title, subtitle, watermark and source line. `bar` (in `BlogChart.tsx`) and `waterfall` +(`BlogWaterfallChart.tsx`) draw with Recharts, Inter, the `--chart-*` tokens and ui-kit's +shared axis, grid, tooltip and legend styles. `stateMap` (`BlogStateMap.tsx`) draws an 11 by +8 tile grid shaded from `--background` to `--primary`. Each file's header comment documents +its spec. + +- Put data and labels in the spec, never styling. Pick series colors by token name: + `primary`, `secondary`, `tertiary`, `quaternary`, `quinary` or `negative`. `positive` maps + to `--success`, which the website does not define, so it falls back to the series palette. +- Do not add matplotlib PNGs or Plotly JSON to new posts. When a post needs a chart type the + website lacks (a line or scatter chart, say), add the type to `website/src/components/blog/` + with tests before the post uses it. +- `website/src/__tests__/components/blog-chart-posts.test.ts` fails CI when a post's chart + block does not parse. Keep the chart's numbers identical to the tables and text beside it. +- The legacy `app/src/components/blog/MarkdownFormatter.tsx` draws charts only from + ` ```plotly ` blocks; a ` ```chart ` block shows there as a JSON code block labeled `chart`. +- The website builds Tailwind with the `tw:` prefix, so ui-kit components that rely on + unprefixed utility classes render unstyled there. Style blog chart parts inline with the + `:root` token variables (`--chart-1`, `--foreground`, `--muted-foreground`, `--border`, + `--font-sans`). +- For a newsletter or social image of a chart, screenshot the chart as the live post renders + it (headless Chromium at 2x) instead of re-plotting it. + ## Anti-patterns ```tsx