💎 Version 5.16.0
Click a data point to drill into a child level, with a breadcrumb trail and back navigation. Supported on bar, column, pie, donut, treemap, and heatmap. Tree-shakeable: import the feature and enable it.
import ApexCharts from 'apexcharts'
import 'apexcharts/features/drilldown'
const options = {
chart: {
type: 'bar',
drilldown: {
enabled: true,
series: [
{ id: 'fruits', name: 'Fruits', data: [{ x: 'Apple', y: 40 }, { x: 'Banana', y: 30 }] },
],
// breadcrumb: { show: true, position: 'top-left', rootLabel: 'All' },
// animation: { zoomFromPoint: true }, // unfold the child from the clicked point
// onDrillDown: async ({ point }) => fetchChild(point), // async level loading
},
},
series: [{ name: 'Categories', data: [{ x: 'Fruits', y: 70, drilldown: 'fruits' }, { x: 'Vegetables', y: 55 }] }],
}
- Child levels are declared inline in
chart.drilldown.series, or fetched on demand viaonDrillDown. - Breadcrumb is configurable (
position,separator,rootLabel,formatter) and includes a back-arrow. - Optional
animation.zoomFromPointunfolds the child level outward from the clicked point (and folds back on drill-up).
Render each slice's name outside the pie, connected by a leader line, so users no longer need to map legend colors back to slices. Pie and donut only (ignored for polarArea). The percentage keeps rendering inside the slice.
plotOptions: {
pie: {
dataLabels: {
external: {
show: true,
// formatter: (name, { percent }) => [name, percent.toFixed(1) + '%'],
// connector: { show: true, width: 1, length: 16, gap: 6 },
},
},
},
}
Spread overlapping scatter points apart. Two uses, one engine. Offsets are in axis units, deterministic (SSR-safe), and applied to the drawn positions only, so tooltips still show the true values.
- Strip plots: pass compact
{ x: 'Category', y: [v1, v2, ...] }data. Each category becomes a band and its values scatter horizontally within it. Every value is a real, hoverable marker; the sticky tooltip follows the hovered dot. - Overplotting: on ordinary
{ x, y }data, add small random offsets so dense clusters fan out.
plotOptions: { scatter: { jitter: { enabled: true, x: 0.35 /*, y: 0, distributed: false */ } } },
series: [
{ name: 'Frankfurt', data: [{ x: 'Frankfurt', y: [120, 118, 130, 109, 142] }] },
{ name: 'Mumbai', data: [{ x: 'Mumbai', y: [182, 176, 195, 168, 201] }] },
]
Marker styling reuses the standard markers / colors / fill config; set jitter.distributed: true to color each band separately.
chart.dataReducer now downsamples rangeArea and rangeBar series via min-max bucket aggregation (preserving the visual extremes of each bucket), complementing the existing LTTB reduction for line/area.
chart: { dataReducer: { enabled: true, threshold: 500, targetPoints: 250 } }
- Drilldown: reset the legend-collapse state when drilling so a child level is not rendered with a parent's series hidden.
💎 Version 5.15.2
An animated chart (e.g. an area chart) schedules a requestAnimationFrame during render() to run its mask-reveal / draw animation. If the chart was destroyed before that frame fired, the stale callback ran against already-cleared DOM and threw:
TypeError: Cannot read properties of null (reading 'node') // in runMaskReveal
The classic trigger is React StrictMode, which mounts → unmounts → remounts a component in development: the first mount queues the animation frame, the unmount calls destroy() (which nulls w.dom.elDefs), and the queued frame then fires against the torn-down chart. Any sufficiently rapid unmount hit the same race.
The fix adds an internal isDestroyed flag, set by destroy() (but not by updates), that the deferred draw-animation callbacks - mask reveal, stroke draw, and bulk reveal - check and bail on before touching the DOM. The flag is cleared on the next render, so re-mounting re-arms animations normally.
This complements the detached-chart destroy() fix in 5.15.1; together they resolve the teardown crashes tracked in react-apexcharts#602.
💎 Version 5.15.1
A small patch release with a single stability fix: charts that are torn down before they ever mount no longer throw.
Calling destroy() (or an internal clear()) on a chart that never finished rendering threw:
TypeError: Cannot read properties of undefined (reading 'node')
This happened when a chart was constructed against an element that wasn't connected to the DOM - so create() bailed out early before building the SVG, leaving w.dom.Paper undefined - and the chart was then destroyed. Common triggers:
- A React
useEffectcleanup (or a Vueunmountedhook) tearing the chart down before the element was ever attached. - A queued resize/
update()firing after the host element had already been removed.
The teardown path now guards on the SVG actually having been created, cancels any pending resize redraw, and tolerates a missing Apex._chartInstances registry, so destroying a never-mounted chart is a safe no-op.
Fixes react-apexcharts#602 and vue-apexcharts#256.
💎 Version 5.15.0
A new, tree-shakeable chart.type: 'violin' that renders a kernel-density curve for each category, with an optional overlay of the individual observations ("jitter") that produced it.
chart: {
type: 'violin',
},
plotOptions: {
violin: {
bandwidthScale: 1, // multiplies the density-derived half-width
normalize: 'individual', // 'individual' → each violin scaled to its own peak
// 'group' → all violins share one scale (widths track density across categories)
points: {
show: true,
shape: 'circle', // 'circle' | 'square'
size: 2.5, // radius (px)
jitter: 0.5, // 0..1 fraction of the half-width to scatter within
constrainToViolin: true,// clamp jitter to the density width at each value
maxPoints: 3000, // cap per violin; excess is stride-thinned
opacity: 0.9,
fillColor: 'series-dark',// 'series-dark' | 'series' | any literal colour
strokeColor: '#fff',
strokeWidth: 1,
// optional colorScale: { colors: [...], min, max, steps } to colour each dot by value
},
},
},
- Available as a tree-shakeable entry:
import ApexCharts from 'apexcharts/violin', or via the full bundle. - Supports horizontal orientation and bimodal (multi-modal) densities.
- The jitter overlay reveals gradually as the violin path animates in (no instant pop-in).
Box plots can now overlay the raw observations behind each box, via plotOptions.boxPlot.points. It's off by default and inert unless a data point supplies a points: number[] array, so existing box-plot charts are unchanged.
plotOptions: {
boxPlot: {
points: {
show: true,
shape: 'circle', // 'circle' | 'square'
size: 2.5,
jitter: 0.5, // 0..1 fraction of the box half-width to scatter within
maxPoints: 3000, // cap per box; excess is stride-thinned
opacity: 0.9,
fillColor: 'series-dark',
strokeColor: '#fff',
strokeWidth: 1,
},
},
},
💎 Version 5.14.0
An opt-in continuous gradient legend for heatmaps that replaces the categorical legend with a color strip and a hover-tracking arrow.
- Honors
legend.position(top / right / bottom / left) and a newalignconfig (start/center/end). - Strip length accepts px or percent (default
'70%'). - Stops are derived from
colorScale.rangesor sampled from the same shade function the cells use, rendered as a smooth midpoint-anchored gradient (green → blue → yellow → red) that matches the shaded cells. - Per-band hover: hovering a range highlights the cells in that range and dims the rest.
- The heatmap legend now renders for single-series charts too.
chart.type: 'pyramid' now matches the geometry users expect: a single continuous triangle whose stages each own a vertical share proportional to their value, with no gaps between segments.
- Stages are trapezoids bounded by the triangle envelope (apex at top, base at
gridWidth) sized by cumulative-value share.
A new, optional, tree-shakeable feature that tweens between chart types instead of the old destroy-and-recreate flicker.
chart: {
animations: {
chartTypeMorph: { enabled: true, speed: 600 }
}
}
Loaded on demand via apexcharts/features/morph. It captures the old SVG paths from the DOM before destroy, maps each one onto the new chart-type's element identity, and seeds the new paths so the existing PathMorphing engine interpolates between them. When the source/target types or series shapes are incompatible it falls back to an instant snap.
- Supported pairs: bar ↔ {pie, donut, radialBar, polarArea}, plus the trivial pie ↔ donut ↔ polarArea cases, and cross-type morphs involving funnel / pyramid / gauge.
- heatmap: fix two color-mapping bugs in the shared treemap/heatmap helper.
- tooltip: align the combo-chart crosshair with the bar on a numeric x-axis.
- annotations: preserve configured opacity on x-axis range rects.
- toolbar: use the rotate-ccw icon for the reset-zoom button.
- svg: fix a concat error for SVG paths starting in
M 0 0(invalid-path edge case). - types: add
toolbar.menuto theApexLocaletype.
💎 Version 5.13.0
This release focuses on a major visual and behavioral overhaul of tooltips, gauges, and the toolbar, alongside a new zoom-aware LTTB downsampler for very large datasets, a new multi-axis zero-alignment option, and a tightening of the public TypeScript surface.
Tooltip box and arrow now anchor off the bar's rendered DOM rect fixing column/datetime alignment in stacked and grouped charts. Adds a connector arrow (default on) and context-aware placement
- New options:
tooltip.arrow: boolean(defaulttrue) — render a connector arrow pointing at the data point.
Three new radial-gauge design knobs and a smoother needle update:
When multiple y-axes mix sign ranges (for example one spans -10..15, another 0..3), their zero lines no longer share a pixel position - so bars from different axes appear to have different baselines. Setting alignZero: true on two or more axes now extends each opted-in axis so y=0 lands at the same pixel.
- Default:
false(no behavior change unless opted in). - Closes #5100.
Replaces the mixed icon set (filled circles, illustrated hand, heavy magnifier) with a coordinated stroke-only Lucide-style set, and wraps the toolbar in a soft glass pill container with hover and selected-button backgrounds.
- Tooltip arrow is on by default (
tooltip.arrow: true). To restore the pre-5.13 look, settooltip.arrow: false. The arrow is auto-suppressed forfollowCursor,fixed.enabled,fillSeriesColor, non-axis charts, and most shared multi-series cases. - TypeScript users on stricter configs may see new errors from the narrowed literal unions on
tooltip.theme,states.filter.type,legend.clusterGroupedSeriesOrientation, andxaxis.axisTicks.borderType. Fix by using one of the documented string values. Reading offopts.wmay also surface, since[key: string]: anywas removed from formatter option types.
💎 Version 5.12.0
- First-class
funnel,pyramid, andgaugechart types — no moretype: 'bar'+isFunnelworkaround. - Per-chart-type initial-mount animations — pen-stroke draws, staggered bar grows, scale-up pops, diagonal heatmap waves, treemap cascades, gauge needle settles, and more.
- TimeScale rewrite — single-resolution stride generator replaces the legacy mix-and-match promotion algorithm. Roughly 2,700 lines of logic removed.
First-class funnel / pyramid / gauge types (8f038155)
chart.type now accepts 'funnel', 'pyramid', and 'gauge' directly. They normalize to the underlying renderer (bar with isFunnel for funnel/pyramid, radialBar for gauge) at config time and preserve chart.requestedType for default selection.
Funnel additions:
plotOptions.funnel.shape: 'rectangle' | 'trapezoid'— trapezoid mode draws continuous sloped sides between consecutive stages.plotOptions.funnel.lastShape: 'flat' | 'taper'— controls whether the final stage tapers to a point.- Trapezoid mode skips the 3D bar-shadow pass (stages are already contiguous).
Gauge additions:
plotOptions.radialBar.shape: 'arc' | 'needle'.- Custom value-to-angle mapping (
min/max). - Configurable bands and ticks that render on both arc and needle shapes.
Samples added under samples/source/funnel/ and samples/source/gauge/.
Accessibility — WCAG 1.4.11 contrast compliance (258def38)
All colours across the 10 built-in theme palettes now pass WCAG 1.4.11 non-text contrast (≥ 3:1) against both the default light and dark backgrounds.
TimeScale refactor (005c4f23)
The time-scale tick generator has been rewritten around a single-resolution stride algorithm. The previous mix-and-match label promotion logic has been removed.
src/modules/TimeScale.jsreduced from ~1,231 lines to a focused stride generator.- New date helpers in
src/utils/DateTime.jsfor tick generation.
- Tooltip — shared sweep coverage (c13f2ebe) — Shared tooltips on line/area charts now capture every datapoint during a mouse sweep instead of skipping points at fast cursor speeds.
- Accessibility — restore #5183 SVG
<title>fix (27bc253c) — The root SVG<title>element is removed again, restoring the original fix that had regressed. - Pie/donut
legend.showForNullSeries = falsecrash (57be77df, #5216) — Settinglegend.showForNullSeries: falseon pie/donut charts no longer throws a runtime error. - Responsive yaxis merge (0ba210b2, fcf46856, #5212) —
yaxisarray entries from aresponsivebreakpoint now deep-merge into the matching base-config entries instead of replacing them wholesale.
- Funnel / pyramid / gauge users: The existing
type: 'bar'+plotOptions.bar.isFunnel: trueandtype: 'radialBar'configurations continue to work. Newtype: 'funnel' | 'pyramid' | 'gauge'is opt-in and recommended for new code — it enables the new shape options and gauge sub-features. - TimeScale: Tick output is generally cleaner but may differ from 5.11.0 at certain ranges. If you snapshot-test rendered SVGs, expect tick-label snapshot churn.
💎 Version 5.11.0
ApexCharts 5.11.0 ships a comprehensive accessibility overhaul targeting WCAG 2.2 Level AA conformance.
Keyboard & Focus
- Focused data points now expose
role="img"and a contextualaria-label(series name, formatted value, category). - Two-stage Escape: first press dismisses the tooltip, second press exits keyboard navigation (WCAG technique G194).
- Keyboard zoom/pan via
+/-/0andShift+Arrowas alternatives to drag gestures. - Toolbar hit targets enlarged to 24×24 CSS px minimum.
- Tooltip is biased away from the focused data point during keyboard navigation.
ARIA & Semantics
- SVG
<title>added alongside the existing<desc>; auto-generatedaria-labelincludes series names when no description is supplied. - Toolbar controls migrated from
div[role=button]to native<button type="button">(first rule of ARIA) - Visually-hidden
role="status" aria-live="polite"region announces zoom/pan/reset actions to screen readers.
Visual & Motion
- New
--apexcharts-focus-colorCSS custom property, themed for light (#008FFB), dark (#FFD500), and high-contrast (#FFFF00) modes — fixes SC 1.4.11 / 2.4.7. Utils.getContrastRatio()WCAG luminance helper added; high-contrast palette validated ≥ 3:1 against#fffin automated tests — fixes SC 1.4.3 / 1.4.11.@media (prefers-reduced-motion: reduce)shrinks all chart animations to near-zero duration — fixes SC 2.2.2.
Tests added: contrast.spec.js, keyboard-trap.spec.js (Playwright), keyboard-zoom.spec.js (Playwright), extended accessibility.spec.js and keyboard-navigation.spec.js.
closestInMultiArray now projects the cursor onto each consecutive line segment rather than measuring distance to the nearest marker. This makes clicking between two markers on a line or area chart reliably pick the correct series — previously, whichever series's marker happened to be closest to the empty space was selected, often giving wrong results when many series clustered together. Bar, scatter, and other non-line chart types retain the existing marker-distance logic.
-
Tooltip —
shared: falseon line charts (#4983):closestInMultiArraywas ignoring Y distance wheneverallSeriesHasEqualXwastrue, causing a tie across all series so the lowest-index series always won. The X-only fast path is now restricted toshared: true; full Euclidean distance is used otherwise, so the actually-hovered series is correctly identified. -
Tooltip —
shared: truemarkerClick: Line chart withshared: truenow correctly reports the clicked series index in themarkerClickevent callback. -
Focus outline on mouse click: Removed the focus outline that incorrectly appeared around the entire chart container on mouse click; focus styles are now shown only during keyboard navigation.
💎 Version 5.10.6
- Legend stays greyed out after re-enabling hidden series; Fixed a regression where toggling a hidden series back on via the legend would leave the legend item in a greyed-out/disabled visual state. (#5189, #5196)
- Focus outline visible on mouse click; Fixed an issue where clicking anywhere on the chart would show a browser focus outline around the entire chart container. The outline now only appears during keyboard navigation.
💎 Version 5.10.5
- Rename "name" field in renamed locale by @gabriele-v in https://github.com/apexcharts/apexcharts.js/pull/5188
- fix: x-axis labels not updating after zoom reset by @Harsh3006 in https://github.com/apexcharts/apexcharts.js/pull/5194
- Fix for data labels on first/last bars hidden in mixed charts due to missing barPad offset. by @Krishna-Chidrawar in https://github.com/apexcharts/apexcharts.js/pull/5192
- fix: x-axis annotations missing on line/area/scatter charts (5.10.4 regression)
- @Harsh3006 made their first contribution in https://github.com/apexcharts/apexcharts.js/pull/5194
- @Krishna-Chidrawar made their first contribution in https://github.com/apexcharts/apexcharts.js/pull/5192
Full Changelog: https://github.com/apexcharts/apexcharts.js/compare/v5.10.4...v5.10.5