Skip to content

v0.3 · MIT · zero runtime dependencies

ChartCraft

39 chart types, one accessible canvas engine, and nothing else in your node_modules.

A framework-agnostic charting core with thin React, Vue, Svelte and Angular wrappers. Every chart ships a screen-reader data table, full keyboard navigation and a colorblind-safe palette — before you configure anything.

npm install @chartcraft/core

One chart instance, six types, real chart.update() calls.

  • 39chart typesline through sankey, choropleth and network
  • 0runtime dependenciesESM, CJS and .d.ts, strict TypeScript
  • 2,114tests, all greenacross core and the four wrappers
  • 3.1 msredraw at 1M pointsmeasured; flat across 1k → 1M
  • WCAG 2.2mapped, by defaultdata table, keyboard nav, live region
  • 4framework wrappersReact, Vue, Svelte and Angular — exact parity

Performance figures come from npm run bench -w @chartcraft/core — 129 measurements of the library's own work (ingest, model, layout, draw calls), not of rasterization. The numbers, and their caveats, are published in the quality audit.

The catalogue

39 chart types, and the judgement to pick one

Every type ships with tooltips, keyboard navigation, a data table and export — there is no "advanced" tier. Each example page is also opinionated about when not to use its type, because picking the wrong form is the most expensive mistake in data visualization.

Open the gallery

Accessibility

Every chart is readable without looking at it

A canvas is one opaque rectangle to assistive technology. So every ChartCraft chart maintains a parallel DOM beside the pixels — generated from the same model, on every update, with zero configuration.

  • A real <table> of the data, visually hidden by default and never out of sync
  • Tab to a chart, walk points with the arrow keys, Enter to activate — on all 39 types
  • A polite live region announces the focused datum as you move
  • prefers-reduced-motion and forced-colors are honoured, not detected and ignored
Read the accessibility guide

The table below the chart is the a11y.table fallback, shown here instead of visually hidden. It is what a screen reader reads, and what exportData() writes to CSV — the same rows, always.

Performance

A million points, redrawn in single-digit milliseconds

LTTB downsampling reduces a series to the plot width once, and the retained model stays reduced — so a resize at one million points costs the same as a resize at one thousand. Then it re-runs inside the zoom window, so detail comes back when you go looking for it.

  • Measured: 3.1 ms to redraw 1M points, flat across four orders of magnitude
  • LTTB itself is sub-linear — 10.7 ms for a million points
  • No per-frame allocation: 200 redraws at 100k points move the heap by −0.4 KB/frame
  • Canvas 2D, one context, no virtual DOM between your data and the pixels
Read the performance guide

Measuring…

Colour

A palette that survives colourblindness — and dark mode

Eight categorical slots, validated pairwise under CVD simulation in both schemes. Colour follows series identity, never rank, so a series keeps its slot when you filter, sort or toggle it. Dark mode is a second designed scheme, not an inversion.

  • Both schemes ship in the library — the swatches below are read from it, not copied
  • Series past slot 8 fall back to marker shape rather than colours that collide
  • Forced-colors mode drops to three system colours and encodes the rest with shape
  • Sequential and diverging ramps for heatmaps, calendars and choropleths
Read the theming guide
light
  • slot 1, #2a78d6
  • slot 2, #eb6834
  • slot 3, #1baf7a
  • slot 4, #eda100
  • slot 5, #e87ba4
  • slot 6, #008300
  • slot 7, #4a3aa7
  • slot 8, #e34948
dark
  • slot 1, #3987e5
  • slot 2, #d95926
  • slot 3, #199e70
  • slot 4, #c98500
  • slot 5, #d55181
  • slot 6, #008300
  • slot 7, #9085e9
  • slot 8, #e66767

Frameworks

One engine, four wrappers, exact parity

Every feature lives in @chartcraft/core. The wrappers own lifecycle, resize observation and event bridging — and nothing else, so there is no feature that exists in one framework and not another, and nothing to port when the next one lands.

  • Options are deep-watched and routed through chart.update(), which diffs
  • The live chart instance is reachable for zoomTo(), exportImage() and exportData()
  • SSR-safe: the chart is created on mount, never at module scope
  • Solid is on the roadmap — the core will not change to get it
See the roadmap

Code to result

This much code, that much chart

Axes are inferred from the data. The legend appears because there are two series. Tooltips, keyboard navigation and the data table are already on. Nothing below is abbreviated for the pitch — it is the whole thing.

import { createChart } from '@chartcraft/core';

const chart = createChart(el, {
  type: 'bar',
  title: 'Revenue by quarter',
  subtitle: 'FY2026, USD millions',
  data: {
    categories: ['Q1', 'Q2', 'Q3', 'Q4'],
    series: [
      { name: 'Product', data: [12.4, 13.1, 14.8, 16.2] },
      { name: 'Services', data: [6.1, 6.4, 7.0, 7.9] },
    ],
  },
});
Renders

Ready in one install

No plugin registry, no license key, no runtime dependencies. Add the core, import a wrapper if you use one, and every chart type on this site is available to you.

npm install @chartcraft/core

MIT licensed. React 18+, Vue 3 and Svelte 4/5 wrappers ship alongside the core; Angular and Solid are on the roadmap.