Charts - Architecture
Understand the chart data model, chart type selection, the compound API, SVG vs Canvas rendering, and the feature surface.
#Usage
import { Chart } from '@primeui/vue-chart';<!-- Use <Chart.Canvas> to render on canvas. -->
<Chart.Svg>
<!-- Use <Chart.Line>, <Chart.Pie>, <Chart.Scatter> to render a different chart. -->
<Chart.Bar :data="data" category-x-field="category" value-y-field="value" />
<Chart.Title />
<Chart.Caption />
<Chart.XAxis />
<Chart.YAxis />
<Chart.ReferenceLine :y="value" />
<Chart.ReferenceBand :y1="start" :y2="end" />
<Chart.Annotation />
<Chart.Legend />
<Chart.Tooltip />
<Chart.Hover />
<Chart.DataLabels />
<Chart.ExportMenu />
<Chart.Accessibility />
<Chart.Responsive />
</Chart.Svg>The root is ChartSvg or ChartCanvas. Every visible feature is a child component: axes, legends, tooltips, data labels. Add it to enable it, remove it to disable it. The block above lists the parts that apply to any chart rather than a single configuration, so a real chart uses only the subset its data calls for.
#First Chart
Start with ChartSvg, one series, a category field, a value field, and two axes. That is enough to get a chart on screen.
Add ChartLegend and ChartTooltip to complete the standard layout. Add ChartZoom or ChartNavigator when users need to explore large ranges.
#Data Model
Chart reads a flat array of objects. Bind field names to series props. The chart reads the values at render time.
const data = [
{ month: 'Jan', revenue: 42, expenses: 31 },
{ month: 'Feb', revenue: 55, expenses: 38 },
{ month: 'Mar', revenue: 48, expenses: 35 }
];<ChartSvg :height="400">
<ChartLine :data="data" category-x-field="month" value-y-field="revenue" name="Revenue" />
<ChartLine :data="data" category-x-field="month" value-y-field="expenses" name="Expenses" />
<ChartXAxis />
<ChartYAxis />
<ChartLegend />
</ChartSvg>Each series binds its own value-y-field. The category-x-field is the x-axis dimension and can be shared across all series. Series can also use separate data arrays when the sources differ. The category domain is the union across all series.
#Chart Types
Pick the chart type before configuring layout or features. The type drives what the x-axis represents, how marks overlap, and what interactions make sense.
| User need | Chart type | Add when needed | Reference |
|---|---|---|---|
| Trends and changes over time | Line & Area | Area fill, stacking, range bands, time-series axis | Line & Area |
| Comparisons across categories | Column & Bar | Grouping, stacking, waterfall, horizontal orientation | Column & Bar |
| Part-to-whole relationships | Pie & Donut | Donut cutout, gauge variant, data labels, custom center slot | Pie & Donut |
| Correlations and distributions | Scatter & Bubble | Bubble sizing, quadrant lines, color scale | Scatter & Bubble |
| Intensity across two categorical dimensions | Heatmap | Color scale, custom cell content, null handling | Heatmap |
| Financial OHLC price data | Candlestick & OHLC | Volume bars via Combo, annotations, navigator | Candlestick & OHLC |
| Multivariate profiles and comparisons | Radar | Fill, multiple series, custom spoke labels | Radar |
| Radial bars proportional to value | Polar | Multiple series, custom colors, labels | Polar |
| Hierarchical part-to-whole | Treemap | Drilldown, hierarchy levels, custom cell content | Treemap |
| Mixed chart types on a shared category axis | Combo | Secondary y-axis, mixed series colors | Combo |
| Multiple charts with shared crosshair and zoom | Synced Charts | Shared legend, shared zoom range | Synced Charts |
#Compound API
ChartSvg and ChartCanvas are the chart roots. They manage layout, scales, the animation loop, and theme. Series, axes, legends, and tooltips are child components that hook into the root when they mount.
The component is the configuration. Adding <ChartLegend /> renders a legend and reserves space for it. Removing it removes the legend. There's no showLegend flag on the root. The same is true for axes, tooltips, zoom, and hover. Every feature is a component to add or remove.
| Part | Purpose |
|---|---|
ChartSvg / ChartCanvas | Root. Manages layout, scales, animation loop, and theme. |
Series (ChartLine, ChartBar, ...) | Draws data marks and binds field names to the data array. |
ChartXAxis / ChartYAxis | Scale labels, grid lines, tick marks, and axis titles. |
ChartLegend | Series labels and visibility toggles. |
ChartTooltip | Hover detail panel. Supports standard, crosshair, and shared modes. |
ChartZoom | Drag-to-zoom and pan within the visible range. |
ChartNavigator | Scrollable window for exploring long time ranges. |
ChartGroup | Syncs crosshair position, zoom range, and legend state across roots. |
<ChartSvg :height="400">
<ChartLine :data="data" category-x-field="month" value-y-field="revenue" />
<ChartXAxis />
<ChartYAxis />
<ChartLegend />
<ChartTooltip />
</ChartSvg>When props change, the root waits until the end of the tick and batches everything into one layout and render pass. Update five series at once and it still costs one frame.
The root passes xScale and yScale into context so children know where to draw. chartArea is the plot area inside the axes and title. isDark and textColor come from the active theme so custom renderers don't have to detect it themselves.
#Dual rendering
SVG is the right default. Switch to Canvas when pushing past a few thousand marks or for streaming updates.
<!-- SVG -->
<ChartSvg :height="400">
<ChartLine :data="data" category-x-field="month" value-y-field="revenue" />
</ChartSvg>
<!-- Canvas: same children, different root -->
<ChartCanvas :height="400">
<ChartLine :data="data" category-x-field="month" value-y-field="revenue" />
</ChartCanvas>SVG renders each mark as a DOM element. It can be styled with CSS, is accessible by default, and works with print and screenshot tools.
Canvas draws everything onto a single <canvas> element on a requestAnimationFrame loop. 100K+ points and streaming updates stay smooth. There's no DOM tree, so CSS selectors don't apply and screen readers can't navigate the element tree. Add ChartAccessibility for keyboard navigation and ARIA with Canvas.
SVG picks up CSS custom properties automatically. Canvas doesn't have DOM access, so theming goes through a theme prop instead. For details, see Theming.
Layout is computed once and shared by both renderers, so geometry, label placement, leader-line routing, and text wrapping match between SVG and Canvas. The one thing that differs is text rasterization: SVG text is drawn by the browser and inherits the operating system's font smoothing, so it reads slightly heavier than the same text painted by Canvas fillText. This is inherent to canvas versus DOM text rendering and is not configurable. Choose the renderer for the performance and accessibility tradeoff, not for label appearance.
#Imperative API
Charts are declarative: props in, render out. Two situations need a manual repaint.
If dark mode is toggled via a class on <html> rather than a reactive theme prop, the canvas pixel buffer doesn't know to repaint. The DOM changed; the canvas didn't.
Props that accept functions (labelFormat, renderMarker, and similar) are compared by reference, not by value, which is what prevents inline arrow functions from causing infinite loops. Replacing one named function with another won't trigger a re-render on its own.
redraw() covers both. Get a typed ref to the chart:
<script setup lang="ts">
import { ref, watch } from 'vue';
import { ChartAccessibility, ChartBar, ChartCanvas, ChartGroup, ChartLegend, ChartLine, ChartNavigator, ChartSvg, ChartTooltip, ChartXAxis, ChartYAxis, ChartZoom } from '@primeui/vue-chart';
const chartRef = ref<InstanceType<typeof ChartSvg>>();
const showCelsius = ref(true);
watch(showCelsius, () => chartRef.value?.redraw());
</script>
<template>
<ChartSvg ref="chartRef">
<ChartLine :data="data" :label-format="showCelsius ? fnCelsius : fnFahrenheit" />
</ChartSvg>
</template>redraw() re-reads every child's current props and repaints in a single pass.
#Animation
Each renderer runs its own animation loop. Entrance animations play on mount, update animations interpolate when data changes, and exit animations play when a series is removed.
For timing, easing, and per-series configuration, see Animation.
#Multi-chart sync
ChartGroup links multiple chart roots so they share state. Legend toggles, crosshair position, and zoom range all sync. Hover one chart and the crosshair moves on all of them.
For configuration and examples, see Synced Charts.
#Feature Surface
Add features after the chart type and data model are clear.
| Feature | Solves | Documentation |
|---|---|---|
| Zoom & Pan | Exploring dense datasets without losing context. | Zoom & Pan |
| Data Labels | Showing exact values directly on marks. | Data Labels |
| Annotations | Adding text, lines, and bands to highlight regions. | Annotations |
| Tooltip | Showing data detail on hover. | Tooltip |
| Legend | Toggling series visibility and labeling multiple series. | Legend |
| Axes | Scale, ticks, labels, and multiple axes. | Axes |
| Reference Lines & Bands | Marking thresholds, averages, and target ranges. | Reference Lines & Bands |
| Navigator | Zooming a visible window over a large time range. | Navigator |
| Export | Saving the chart as an image. | Export |
| Accessibility | Keyboard navigation and ARIA for Canvas mode. | Accessibility |
| Theming | Custom colors, fonts, and style tokens. | Theming |
| Responsive | Adapting layout to container size. | Responsive |