Getting Started

Migrate from 0.6

Breaking changes in vccs 1.0 and how to update

vccs 1.0 rebuilds every chart on Vue and settles the public API. Most apps need only the checklist below. The sections after it list every change, grouped by what you update, with a before and after example.

  1. Install vue@^3.5 and motion-v@^2.4.
  2. Replace callback props with Vue events: :onClick becomes @click.
  3. Use v-model:active-index (number | null) on Tooltip, Bar and Pie, and v-model:range on Brush.
  4. Remove the responsive prop and sizing-only ResponsiveContainer wrappers; set height on the chart.
  5. Import only public components, composables and types; useOffset becomes usePlotArea.
  6. Update CSS selectors to the v-charts- classes, and colors to the theming tokens.
  7. Rename the props in Renamed props.

There are no aliases for renamed props. ResponsiveContainer and Customized still work in 1.0, warn once in development, and are removed in 2.0.

Dependencies and setup

ChangeWhat to do
The peer dependencies are vue@^3.5 and motion-v@^2.4.Update both. pnpm add vue@^3.5 motion-v@^2.4
Charts are responsive by default. The responsive prop is removed.Before: <BarChart responsive :height="300">. After: <BarChart :height="300">. Set numeric width and height for a fixed size.
ResponsiveContainer is deprecated and no longer passes width and height to its child.Before: <ResponsiveContainer width="100%" :height="300"><BarChart>…</BarChart></ResponsiveContainer>. After: <BarChart :height="300">…</BarChart>.
ResponsiveContainer reports resizes as an event.Before: <ResponsiveContainer :on-resize="resize" />. After: <ResponsiveContainer @resize="resize" />, or remove the wrapper.
Customized is deprecated.Before: <Customized><template #default="{ offset }">…</template></Customized>. After: a child component in the chart's default slot that calls usePlotArea(). See Custom overlays.

New in 1.0, with nothing to migrate: a Nuxt 4 module (vccs/nuxt) and a resolver for unplugin-vue-components (vccs/resolver). See Installation.

Templates: models and events

ChangeWhat to do
Callback props (:onClick, :onAnimationEnd, Brush onChange, …) are Vue events.Before: <Bar :onClick="select" />. After: <Bar @click="select" />; also @animation-end and @change. JSX onClick={…} keeps working.
Item events receive (item, index, event).Before: function select(item, event) { … }. After: function select(item, index, event) { … }.
Active models use number | null. A value you pass controls the display on Tooltip, Bar and Pie.Before: <Bar :active-index="-1" data-key="value" />. After: <Bar v-model:active-index="active" data-key="value" />, with ref<number | null>(null).
Brush uses one nullable range model. A range you pass is controlled by the parent.Before: <Brush :start-index="from" :end-index="to" :on-change="r => { from = r.startIndex; to = r.endIndex }" />. After: <Brush v-model:range="range" />, with ref<BrushStartEndIndex | null>({ startIndex: 0, endIndex: 5 }). null shows all rows and hides the travellers. Bounds are floored, clamped and ordered.
Treemap, Sankey and SunburstChart support the keyboard, so node-click can receive a KeyboardEvent.Before: (node, index, event: MouseEvent). After: (node, index, event: MouseEvent | KeyboardEvent). Check event instanceof MouseEvent before you read pointer coordinates.

Templates: props

ChangeWhat to do
Line and Area dot and activeDot accept boolean or an options object. A function was ignored.Before: :dot="renderDot" (ignored). After: <template #dot="p">…</template>, and #activeDot for the active dot.
Line and Area no longer accept internal geometry or active-point props: points, path, baseLine, layout, left, top, width, height, animationId, activePoint, needClip, activeIndex.Before: <Line data-key="value" :points="points" />. After: <Line data-key="value" />. Set data, layout and size on the chart; use the series slots for custom shapes.
Bar no longer accepts the internal needClip and id props.Before: <Bar data-key="value" id="bars" :need-clip="true" />. After: <Bar data-key="value" />. Axis overflow settings control clipping.
Legend no longer accepts chartWidth, chartHeight or margin.Before: <Legend :chart-width="500" :margin="margin" />. After: <Legend />. Set the size and margin on the chart.
Label no longer accepts parentViewBox or index.Before: <Label :parent-view-box="box" :index="0" value="A" />. After: <Label :view-box="box" value="A" />. Use a LabelList content slot when you need the item index.
Each chart family accepts only its own props. to and throttleDelay are removed.Before: <BarChart :cx="100" :throttle-delay="50" />. After: <BarChart />. Pie and Radar charts drop the bar sizing props, Funnel charts drop bar sizing and polar props. These props had no effect.
The chart dataKey prop is removed. It was never read.Before: <BarChart data-key="x">. After: <BarChart>.
The Brush data prop is removed. It was never read; Brush always uses the chart data.Before: <Brush :data="rows" />. After: <Brush />, with data on the chart.
Series inherit the chart's animation settings; a series prop still overrides them.Before: :is-animation-active="false" on every series. After: <BarChart :is-animation-active="false"> once.
XAxis and YAxis type orientation, type, padding and scale, and declare tick, angle, label, name, stroke and tickSize.Before: <XAxis orientation="sideways" /> compiled. After: it is a type error; YAxis accepts left or right, and padding accepts the axis object, gap or no-gap.
YAxis defaults yAxisId to 0.Before: <YAxis :y-axis-id="0" />. After: <YAxis />. Explicit ids still work.
Brush no longer declares an ariaLabel prop, so aria-label reaches the brush group.Before: <Brush aria-label="Date range" /> was dropped. After: the same template labels the brush.

Renamed props

ChangeBeforeAfter
Tooltip content<Tooltip :content="renderTooltip" /><Tooltip><template #content="props">…</template></Tooltip>
Tooltip default slot<Tooltip><div>…</div></Tooltip><Tooltip><template #content><div>…</div></template></Tooltip>
Tooltip teleport target<Tooltip :portal="element" /><Tooltip :to="element" />; a CSS selector also works
Legend teleport target<Legend :portal="element" /><Legend :to="element" />; a CSS selector also works
Treemap palette<Treemap :color-panel="palette" /><Treemap :colors="palette" />
Treemap tile proportions<Treemap :aspect-ratio="1" /><Treemap :tile-aspect-ratio="1" />; aspect now sets the chart's proportions

Imports and types

ChangeWhat to do
Internal contexts, payload searchers, path builders, Global, *VueProps and internal types are no longer exported.Before: import { LineVueProps, getPath } from 'vccs'. After: import { Curve } from 'vccs' and import type { LineProps } from 'vccs'.
useOffset is removed.Before: const { left, top } = useOffset().value. After: const { x, y } = usePlotArea().value.
Composables keep their runtime nullability in the types.Before: useActiveTooltipCoordinate().value.x. After: useActiveTooltipCoordinate().value?.x.
Every public XxxProps type comes from its component's props. LineProps no longer has animateNewValues; FunnelProps has fill and class; CartesianAxisProps no longer requires scale.Remove props the component never had.
*PropsWithSVG types are removed: LinePropsWithSVG, FunnelPropsWithSVG, LegendPropsWithSVG, PiePropsWithSVG, RadialBarPropsWithSVG, RectanglePropsWithSVG, SectorPropsWithSVG. XxxProps holds the declared props and events only; templates still accept SVG attributes such as stroke-dasharray.Before: LinePropsWithSVG. After: LineProps. Type SVG attributes you pass in code as SVGAttributes from vue.
The trapezoid geometry type is renamed: TrapezoidProps becomes TrapezoidItem, and TrapezoidComponentProps becomes TrapezoidProps.XxxProps always means a component's props. Rename the imports.
Bar #shape and #activeBar slots receive numeric geometry.Before: #shape="{ x }" could receive undefined. After: x is a number; a bar without geometry calls no slot.
Scatter payloads omit tooltipPosition when a coordinate is missing.Guard point.tooltipPosition before you read it.
Point has one definition, with an optional readonly payload.Nothing, unless you built objects that must not have payload.
Folder entry points such as vccs/src/cartesian are gone.Import from vccs only.
The transition type is ChartTransition.Before: const transition = { duration: 0.2 }, typed with a motion-v type. After: const transition: ChartTransition = { duration: 0.2 }, imported from vccs.

Styles and colors

ChangeWhat to do
All classes use the v-charts- prefix in kebab case. The unprefixed xAxis and yAxis classes are removed.Before: .vcharts-surface, .recharts-brush-traveller, .v-charts-errorBar. After: .v-charts-surface, .v-charts-brush-traveller, .v-charts-error-bar.
Default colors are CSS variables, for example stroke="var(--v-charts-grid, #ccc)".Before: [stroke='#ccc'] { … }. After: set the tokens on the Theming page.
Series without a color take --v-charts-series-1 to --v-charts-series-8. Bar and Scatter have a default fill.Set the numbered tokens, or give each series an explicit color.
Bar no longer sets strokeWidth to 0, so a stroke shows. React-style attributes such as strokeWidth reach the SVG as stroke-width.Remove a stroke you did not want to see.
Tooltip text uses the tooltip foreground, and series colors move to swatches. Legend items contain native buttons.Style .v-charts-tooltip-swatch and .v-charts-legend-item button.
Text on known opaque fills is black or white. Variable and translucent fills use --v-charts-label-foreground.Set --v-charts-label-foreground for custom fills, and check both themes.
Bar class is set once on the series layer ([data-slot=series].v-charts-bar), not on every rectangle. Every series layer gets its class; Scatter, Radar and RadialBar accept class.Before: .my-bars { … } matched each rect. After: .my-bars .v-charts-bar-rectangle { … }.
<Area stroke="none"> hides the outline; the legend, tooltip and active dot then use the fill. The Area active dot uses the stroke color (it used the fill).Set stroke to the color you want on the outline and the active dot.
Pie, RadialBar and Funnel tooltip swatches show the entry color, and Scatter swatches the series fill. The Pie legend and Funnel labels use <Cell fill>.Read color and fill from the #content payload if you draw your own swatch.

Style chart parts with data-slot: chart, surface, plot, grid, x-axis, y-axis, angle-axis, radius-axis, series, tooltip, legend, brush, cell and label.

Accessible names and markup

ChangeWhat to do
Every chart has an accessible name, and accepts title and desc.Before: no name. After: <BarChart title="Visits" desc="Visits per month">; the default is the chart type, for example Bar chart.
Item attributes use the vccs prefix.Before: data-recharts-item-index, data-recharts-item-data-key. After: data-v-charts-item-index, data-v-charts-item-data-key.
Brush travellers announce category indexes instead of pixel coordinates.Read positions from geometry attributes; aria-value* describes the data range.
Generated SVG ids use Vue's useId().Do not select elements by generated ids; pass id to the chart for a stable one.

Tooltip payloads of Treemap and Sankey

Treemap and Sankey give the tooltip the same payload shape as the cartesian charts: payload is your node or link, and value is the raw number. One #content template works for every chart.

ChangeWhat to do
payload[0].payload is your own node or link object. Before it was a copy with an internal tooltipIndex, and for Sankey with layout fields (x0, y0, …).Before: payload[0].payload.tooltipIndex. After: read your own fields from payload[0].payload. Layout fields come with the node-* events and the #node slot.
A Tooltip formatter receives the raw value and wins over a chart's default formatter.Nothing. Before, a chart default could hide your formatter.
A Treemap parent node shows its real name and the sum of its leaves. Before it showed root and its own field.Nothing.
The Label #content slot receives the normalized viewBox: missing sizes and angles are 0.Nothing, unless you checked for undefined.

Behavior changes

These changes need no code change in most apps.

ChangeWhat to do
Elements share one default timing: 1 s enter, 0.5 s update, 0.3 s exit (see Animation). Lines appear with a left-to-right sweep instead of drawing their stroke.Pass :transition to keep a custom timing.
Charts follow a resize at once; only data changes animate. Axis ticks and grid lines animate with the series.Set :is-animation-active="false" on the chart to keep it still.
Series hidden from the legend animate out and back in.Nothing.
Legend entries and tooltip rows keep the data or series order. Before, they were sorted by name.Pass item-sorter="value" (Legend) or item-sorter="name" (Tooltip) to sort as before.
An uncontrolled Brush keeps its window when data updates. Before, it snapped back to the last row on every new array.Nothing. Rows added while the window ends at the last row move it forward with the same width; removed rows clamp it. A moved window emits update:range.
Pie respects hide.Remove workarounds for a hidden pie that still rendered.
Non-finite values (Infinity, NaN) count as missing. Numeric strings ("12") count as numbers in Pie, Funnel, Treemap and SunburstChart. Sankey drops links to missing nodes and links that close a cycle, with a development warning.Nothing, unless you relied on the old output.
allowDataOverflow on one axis clips only that axis (Line, Bar), and Area clips like Line.Nothing. Before, both axes were clipped and Area never was.
reverseStackOrder works: true puts the last stacked series at the base, as in Recharts.Before, true and false drew the same stack. Remove the prop if you relied on that.
The chart role prop applies to the SVG (or to the wrapper with the accessibility layer).Nothing. Before, it was dropped.
Funnel marks the hovered trapezoid active, as keyboard selection did. In a ComposedChart, the Scatter point at the active index is enlarged.Nothing.
A function data-key no longer shows its source code as a name. Pie and Funnel accept name, and a Pie sector without a name-key value is named by its row index.Set name on the series, or name-key on the Pie.
Radar legend values and Radar and RadialBar tooltip names use name, then a string dataKey.Set name when dataKey is a function.
Series tooltip entries carry the series strokeWidth (Line default 1).Nothing.
Numeric and string axis ids name the same axis (y-axis-id="1" and :y-axis-id="1").Nothing. Before, a mix created a second, empty axis.
PolarGrid polygon paths drop their spaces (M x,yL x,y becomes Mx,yLx,y). The geometry is the same.Update snapshot tests.
Copyright © 2026