ApexCharts 6.10.0 shipped on August 18, 2026 with apexcharts/unit-shapes, a kit of 39 shapes a unit chart can pack its dots into, plus outer name labels and two fixes. Nothing is breaking, but update() now re-renders when only a function-valued option changes, so check the table below if you pass a fresh callback on every update.

Key takeaways

  • New apexcharts/unit-shapes entry point: 39 packable shapes, tree-shaken, about 4 KB gzipped per shape.
  • Three kinds plus helpers: 29 silhouettes, 7 strokes, 3 generated, with outlined(), .with({ order }), glyphs() and preview().
  • Outer name labels: clusterLabels.external names each band of a custom layout in the margin instead of a legend.
  • Fix: update() no longer discards an update that changes only a function value.
  • Fix: a Date as x keeps its milliseconds, and the types accept it.
  • Upgrading is npm install apexcharts@^6.10.0.

Which defaults changed?

ChangeReleaseWhat you will seeHow to reverse it
update() compares function-valued options by identity6.10.0A new dataLabels.formatter, custom tooltip or plotOptions.unit.positions now renders; a fresh closure on every update renders every timePass the same function reference to skip the render. Discarding a changed function was a bug, so there is no switch
// Before 6.10.0 the second call was discarded. Both now render.
chart.updateOptions({ dataLabels: { formatter: (v) => `${v} units` } })
chart.updateOptions({ dataLabels: { formatter: (v) => `${v} kg` } })

Unit shapes

A shape is a plain callable, so it goes straight into plotOptions.unit.positions with no registration step. The dots are packed rather than stamped, so one outline serves 40 dots in a sparkline and 3,000 in a poster. The demo swaps positions on one chart: the same 820 marks, seven arrangements.

positions: house. 29 silhouettes fill an outline.

820 households, one dot each. Only positions changes between these seven views: same instance, same marks, same colours, so every dot carries its value from one shape into the next.

import ApexCharts from 'apexcharts'
import { heart } from 'apexcharts/unit-shapes'

new ApexCharts(el, {
  chart: { type: 'unit' },
  series: [57600, 16800, 4200, 3400],
  labels: ['Repeat donors', 'First-time', 'Workplace drives', 'Emergency call-ups'],
  plotOptions: {
    unit: { layout: 'custom', positions: heart, unitValue: 100 },
  },
}).render()

Silhouettes fill an outline (heart, house, battery), strokes pack a thickened centreline for things with no interior (check, pulse), and generated shapes compute positions from maths (globe, target, pyramid). outlined() traces a silhouette instead of filling it, .with({ order: 'cols' }) sets where each series band lands, glyphs('1,024') draws a number in that many dots, and preview() returns an SVG string with no chart or DOM. Browse all 39 shapes or read the unit shapes docs.

Outer name labels

Names can now sit in the margin (with layout: 'custom') with a leader line to their own dots, the way a pie names its slices, so a shape packed with several categories reads without a legend.

plotOptions: {
  unit: { layout: 'custom', clusterLabels: { external: { show: true } } },
}

The gutter is reserved before the dot size is chosen, so below roughly 520px of chart width the shape itself goes small. Give an outer-labelled chart a full-width card, or drop back to a legend at narrow sizes. See Outer Name Labels.

A funnel silhouette with outer name labels

Bring your own shape

positions is a function from the marks and the plot rectangle to places, and every shape in the kit is one of those. shapeFrom() packs your own SVG outline exactly like the built-ins, and strokeFrom() takes a centreline and a width for a thing that is a line.

import { shapeFrom, strokeFrom } from 'apexcharts/unit-shapes'

const paw = shapeFrom('M 26 71 A 24 21 0 1 1 74 71 ...', { name: 'paw', minUnits: 180 })
const ridge = strokeFrom('M 6 76 L 24 44 L 40 60 ...', { width: 12, order: 'cols' })

When authoring an outline, check the winding first: a subpath wound the other way cuts a hole. See Bring Your Own Shape.

Three routes to your own shape

Other fixes

  • A data point whose x is a Date keeps its milliseconds, so points inside the same second no longer collapse, and the type definitions accept a Date there. Thanks to @aron-intframe (#5277).

The full list is in the 6.10.0 GitHub release.

Upgrading

npm install apexcharts@^6.10.0

Or with a script tag:

<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/6.10.0/apexcharts.min.js"></script>

The shape kit needs apexcharts >= 6.10.0, including the update() fix.

The unit chart is a Premium chart type. Without a licence key it renders with an APEXCHARTS trial watermark; the shape kit adds no further requirement. The rest of the library is covered by the Community License, free under $2M in annual revenue, budget or funding. See pricing.

Frequently asked questions

Is a unit shape an image or an SVG file I ship?

Neither. A shape is code that places marks: rows are cut across the outline, split into the spans inside it, and the spacing is bisected until the spans hold exactly the number of dots the data asks for. Change the count and it repacks.

How much does apexcharts/unit-shapes add to my bundle?

The whole catalog is about 48 KB raw and 14 KB gzipped, tree-shaken per shape, so one shape costs roughly 4 KB gzipped. Importing the `catalog` export pulls in all 39, which suits galleries and tests rather than charts.

Why did my unit chart morph once and then freeze before 6.10?

That was the `update()` bug, not a shape bug: an update that changed only a function was skipped. Upgrade to 6.10.0, where functions are compared by identity.

Can I pack dots into a shape that is not in the kit?

Yes. Pass an SVG outline to `shapeFrom()`, or a centreline and a width to `strokeFrom()`, and the built-in engine packs it. Any function returning `{ id, x, y }` per mark also works as `plotOptions.unit.positions` without importing the kit.