vue-chartjs

A Vue.js wrapper for Chart.js that turns chart configs into reusable, reactive chart components.

Library
npm
v5.3.4
5,717 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
68 /100 Good
Development Activity 48
Maintenance 44
Community 80
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
75 /100 Good
Architecture 85
Code Quality 80
Innovation 78
Learning Curve 55

vue-chartjs wraps Chart.js so Vue applications can render charts as ordinary components instead of imperatively managing a canvas and a Chart.js instance by hand. It ships a typed component for every Chart.js chart type (Bar, Line, Pie, Doughnut, PolarArea, Radar, Bubble, Scatter) plus a generic Chart component and a createTypedChart factory for building your own, so only the specific Chart.js controllers a chart needs get registered.

Under the hood it watches the data and options props, unwraps them from Vue’s reactivity proxies, and calls Chart.js’s own update() method with a configurable update mode instead of tearing down and recreating the chart on every change. The result is a thin, TypeScript-first bridge that stays close to Chart.js’s native configuration shape while handling the Vue-specific plumbing (reactivity, lifecycle, refs, accessibility attributes) that would otherwise be repeated in every project that pairs the two libraries.

What You Get

  • Prebuilt, typed Vue components for every core Chart.js chart type: Bar, Line, Pie, Doughnut, PolarArea, Radar, Bubble, and Scatter
  • A generic Chart component that accepts any Chart.js chart type via a type prop
  • A createTypedChart factory for generating your own typed component around a Chart.js controller the package doesn’t ship a shortcut for
  • Reactive data/options props that call Chart.js’s update() method instead of forcing a full re-render
  • Event helper utilities (getDatasetAtEvent, getElementAtEvent, getElementsAtEvent) for wiring chart click interactions
  • Support for both Vue 2.7 and Vue 3 from the same package via internal compat handling

Common Use Cases

  • Admin and analytics dashboards that visualize product or business metrics
  • SaaS reporting pages driven by live data from a Pinia or Vuex store
  • Embedding charts in Vue-based internal tools without writing raw Chart.js setup code
  • Interactive charts where clicking a bar, slice, or point drills into per-dataset detail views

Under The Hood

Architecture

The codebase is small and deliberately layered: src/chart.ts defines the core Chart component that owns the canvas ref and a shallowRef to the live Chart.js instance, wires onMounted/onUnmounted lifecycle hooks, and runs a deep watcher on the data/options props that diffs cloned data against Chart.js’s own config object before calling chart.update(). src/typedCharts.ts layers a createTypedChart factory on top of that core component: it registers only the specific Chart.js controller (BarController, LineController, DoughnutController, etc.) a given chart type needs and re-forwards a ref so callers can reach the underlying Chart.js instance. src/utils.ts isolates all the Vue-reactivity-proxy handling (toRawIfProxy, cloneProxy, cloneData/setDatasets/setLabels) that keeps Chart.js’s in-place config mutation safe against Vue’s reactive proxies, and props/types live in their own files. Every typed chart component composes the same core Chart component, so its diffing logic is a single point every chart type depends on.

Tech Stack

TypeScript in strict mode (noUnusedLocals, noImplicitReturns, isolatedModules) targeting ESNext, with Vue 3 as the primary peer dependency and Vue 2.7 supported via a version-string branch in compatProps. Chart.js v4 (BarController, LineController, etc.) is the other peer dependency. The package is bundled with Rollup (rollup-plugin-swc3) into dual ESM/CJS output, developed against Vite and tested with Vitest plus @vue/test-utils; Storybook (@storybook/vue3) hosts interactive chart sandboxes, tsd runs type-level tests, and size-limit enforces a bundle-size budget. Release tooling (commitlint, simple-git-hooks, standard-version, simple-github-release) automates versioning and changelog generation, and the whole project runs on pnpm.

Code Quality

Each typed chart component has a corresponding Vitest spec (Bar.spec.ts, Line.spec.ts, Doughnut.spec.ts, Pie.spec.ts, PolarArea.spec.ts, Radar.spec.ts, Bubble.spec.ts, Scatter.spec.ts) that mounts the component against fixture configs under sandboxes/*/src/chartConfig.js and asserts canvas rendering, id passthrough, and plugin wiring; a separate types.test-d.ts uses tsd to assert the exported type surface compiles correctly. Error handling is intentionally minimal (simple guard clauses rather than thrown/typed errors), which is reasonable for a thin wrapper library. Naming is consistent and descriptive throughout (setLabels/setDatasets/cloneData), TypeScript strict mode is enforced end to end, and ESLint plus Prettier run via pre-commit hooks. CI (checks.yml, ci.yml) runs type-checking, unit tests, and a Storybook build on every pull request.

API Design The public API stays deliberately close to Chart.js’s own configuration shape: consumers import a named component (Bar, Line, Pie, …) or the generic Chart with a type prop, and pass data/options objects matching Chart.js’s documented config directly, so there is no bespoke configuration DSL to learn beyond Chart.js’s own docs. createTypedChart is exported so teams can generate their own typed wrapper for a chart type the package doesn’t ship a shortcut for, and an exposed chart ref gives an escape hatch to the underlying Chart.js instance for anything the props API doesn’t cover. The main friction point is that consumers still need to explicitly register the Chart.js controllers/elements a chart type uses via ChartJS.register(…), which is a small but real bit of boilerplate carried over from Chart.js itself.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers