Skip to content

Chart.js libraries comparison

Chart.js is the most-installed canvas charting library on the web, and, unlike FullCalendar, it ships no official framework connectors. Every framework binding is a separate community project, and the quality varies wildly: React and Vue are served by large, healthy wrappers; Angular and Svelte have solid maintained ones; Solid's only option has been frozen since mid-2024; and Lit has no modern Chart.js wrapper at all.

Rozie's @rozie-ui/chartjs ships the same Chart to every framework in your stack: the same generic component (the type prop drives the whole controller set), the same three structured events, the same fifteen-verb imperative handle, the same external-HTML tooltip portal slot, and the same :plugins passthrough on React, Vue, Svelte, Angular, Solid, and Lit alike. Each framework installs a pre-compiled @rozie-ui/chartjs-* package with no Rozie toolchain required.

Every wrapper on this page, including Rozie's, drives the same chart.js engine, current major v4 (4.5.x). The engine is shared and well-maintained, so this comparison is purely about the per-framework binding layer: which frameworks have a binding at all, how current it is, and how consistent the events / imperative-handle / custom-tooltip story is across them.

Comparison matrix

Cell legend: = documented out-of-the-box · = not supported / not present · ~ = partial / consumer-glue-required / not documented. ("Not documented" is scored ~, never : absence of documentation is not evidence of absence.)

WrapperFrameworksLatest publishedFramework supportStructured eventsImperative handleHTML-tooltip slotPer-type componentsSelective (tree-shakable) registration
Rozie @rozie-ui/chartjs6 — React + Vue + Svelte + Angular + Solid + Litpre-1.0, released togetherR18+ / V3.4+ / Sv5 / Ng19+ signals / Solid / Lit3 uniform (click/hover/datasetClick, structured, composed) on all 6uniform $expose (15 verbs) on all 6portal slot on all 68 typed components + generic Chart, all 6✓ consumer-registers + /auto entry (per-type tree-shakes on source leaves)
react-chartjs-2React5.3.1 · 2025-10React 16.8 – 19~ options.onClick + getElement*AtEvent helpers (no React events)ref → Chart.js instance✗ external-handler only (no React slot)✓ 8 typed + generic Chart✓ typed components auto-register their controller
vue-chartjsVue 35.3.4 · 2026-07Vue 3 (3.x+)✗ emits no Vue eventsref.chart → instance✗ external-handler only (canvas-fallback slot only)✓ 8 typed + generic + createTypedChart✓ manual ChartJS.register(...)
ng2-chartsAngular10.0.0 · 2026-03 (v8 = Ng19)Angular ≥ 21 on v10; earlier majors cover 17 – 20 (no signals — @Input/OnChanges)chartClick / chartHover (2, Angular only)ViewChild(BaseChartDirective).chart✗ no ng-template tooltip~ one canvas[baseChart] directive (type input)provideCharts(...) selective
svelte-chartjsSvelte4.0.1 · 2026-03Svelte 5~ getElement*AtEvent helpers (no Svelte events)bind:chart → instance✗ external-handler only✓ 8 typed + generic✓ manual ChartJS.register(...)
solid-chartjsSolid1.3.11 · 2024-07 (frozen)Solid 1.7+✗ none documented~ not documented✓ typed + DefaultChart✓ manual register
Litno modern Chart.js wrapper exists

Weekly downloads (npm, snapshot 2026-08-03→08-09, a popularity datum rather than a quality verdict): react-chartjs-2 ≈4,320,888 · vue-chartjs ≈1,004,541 · ng2-charts ≈446,627 · svelte-chartjs ≈61,002 · solid-chartjs ≈12,894 · chartjs-web-components (the dead Lit option) ≈19 · Rozie @rozie-ui/chartjs: new.

All competitor facts were verified against the npm registry, the GitHub API, and each project's README / source / package.json on 2026-08-10; re-check the dates before relying on them.

Where Rozie wins today

  • First-class packages for all six frameworks, including the two the ecosystem leaves stagnant or empty. Chart.js has no official connectors, so the matrix is a patchwork: React (≈4.3M/wk) and Vue (≈1.0M/wk) are healthy; Angular (ng2-charts, ≈0.45M/wk) and Svelte (svelte-chartjs, Svelte-5-ready) are solid and current; Solid's only wrapper has been frozen since 2024-07 with no documented instance or event API; and Lit has no modern Chart.js wrapper at all (the only named package targets Chart.js 2.x / lit-element 1.x and was last touched in 2021). A team standardizing on Chart.js gets two big wrappers, two solid ones, one stagnant package, and one hole. Rozie fills the whole row with the same component.

  • A uniform, structured event surface. This is the single biggest capability difference. Chart.js click/hover handling fragments badly per framework: react-chartjs-2 and svelte-chartjs give you options.onClick plus exported getElementAtEvent helper functions (no framework events); vue-chartjs emits no Vue events at all; ng2-charts is the only one with native framework events (chartClick / chartHover); Solid and Lit have none. Rozie surfaces three events, @click / @hover / @datasetClick, with structured payloads ({ event, elements, chart }, the hit elements already resolved via getElementsAtEventForMode). Each is composed over any consumer-supplied options.onClick/onHover rather than clobbering it. One event shape to learn once, on any framework.

  • The external-HTML tooltip as a first-class portal slot, everywhere. No competitor offers a framework-native tooltip slot or render-prop. On every one of them a custom HTML tooltip means hand-writing options.plugins.tooltip.external, a DOM-building callback that lives outside the framework's rendering model. Rozie surfaces it as one tooltip portal slot that emits the framework's idiomatic consumer surface (React/Solid render-prop, Vue scoped-slot, Svelte snippet, Angular ng-template content-child, Lit slot bridge), fed the live tooltip model ({ title, body, dataPoints, opacity }). The slot is guarded: omit it and you get Chart.js's default canvas tooltip on every target. Because canvas owns its own paint, the external tooltip is the one place a framework-native fragment can render over the chart, so Rozie implements that one well.

  • A uniform imperative handle. Every competitor exposes the Chart.js instance its own way: a React ref to the instance, vue-chartjs's ref.chart, ng2-charts's ViewChild(BaseChartDirective).chart, svelte-chartjs's bind:chart, and nothing documented on Solid/Lit. Rozie's $expose handle is the same fifteen verbs — getChart / updateChart / resizeChart / resetChart / renderChart / stopChart / clearChart / getActiveElements / setActiveElements / getDatasetMeta / isDatasetVisible / setDatasetVisibility / showDataset / hideDataset / toBase64Image (PNG export) — on every target, grabbed with each framework's native ref mechanism. getChart() returns the raw instance, so the full Chart.js API is always one hop away.

  • Per-type components and selective registration, at parity with react-chartjs-2. Each package exports the eight per-type components (Line/Bar/…/Bubble), each registering only its own controller set, alongside the generic Chart, which no longer auto-registers (the consumer registers what they use, or imports the /auto kitchen-sink entry). The bundled React/Solid/Lit packages expose a per-variant subpath for each typed component (@rozie-ui/chartjs-react/line, …/bar, …), each resolving to its own isolated chunk, so importing /line ships only Line's registration; the source-shipped Vue/Svelte/Angular packages tree-shake per-type imports natively. The datasetIdKey prop and the a11y fallback slot (in-canvas fallback content alongside ariaLabel) round out react/vue wrapper parity.

  • Angular emitted in the signals idiom. ng2-charts, the dominant Angular wrapper, is a canvas[baseChart] directive built on @Input() + OnChanges, not Angular's signals model. Rozie's @rozie-ui/chartjs-angular is a standalone component whose props are signal input()s and whose reactivity runs through effect(), the Angular-19+ idiom, with the same (click)/(hover) outputs and viewChild-grabbable handle.

  • :plugins consumer-extensibility, applied uniformly. Chart.js plugins (datalabels, annotation, zoom, a custom crosshair) are passed per-instance through :plugins, with no per-plugin wrapper code and zero bundle cost for plugins you don't engage. This matches the per-instance plugins prop the React/Vue/Svelte wrappers also offer; the parity point is that Rozie does it the same way everywhere.

What Rozie defers

  • React 19 and Svelte 5 are already covered upstream. Unlike the FullCalendar comparison, version currency is not a differentiator here: react-chartjs-2@5.3.1 already lists react@^19 in its peer range, and svelte-chartjs@4.0.1 already targets Svelte 5. Rozie installs cleanly against React 19 and Svelte 5 too, matching the ecosystem on currency rather than leading it. Rozie's advantage on React/Vue/Angular/Svelte is the uniform cross-framework surface.

  • Single-framework ergonomics are not the contest. The matrix scores out-of-the-box, cross-framework capability. On its home framework each of these is a solid pick; for a single-React or single-Vue app, react-chartjs-2 / vue-chartjs are large, battle-tested libraries and the obvious choice. The case for Rozie is one component, with one events/handle/tooltip surface to learn, document, and migrate, including where the Solid wrapper is frozen and the Lit one doesn't exist.

Try it

The @rozie-ui/chartjs showcase + API reference documents the @rozie-ui/chartjs-* packages — one pre-compiled, per-framework install (npm i @rozie-ui/chartjs-react chart.js, etc.). The ChartScreenshotDemo source renders line, bar, and doughnut from the one generic Chart, and the ChartBehaviorDemo source drives runtime type-switching, the @click event, the :plugins passthrough, and the tooltip portal slot.

Pre-1.0 — APIs may change between minor versions.