Migrating from ApexCharts 4.x
Switching an existing app: what is identical, what is new, what behaves differently.
WestCoast Charts started from the MIT-licensed ApexCharts 4.7.0 source and keeps an ApexCharts-style configuration model for familiar options, methods and events. This is not a guarantee of unchanged behaviour for every application. Review the differences in themes, accessibility, text escaping, sanitization and validation below, then test your actual charts before switching.
ApexCharts is a trademark of its owner. WestCoast Charts is an independent project by West Coast Software and is not affiliated with, sponsored or endorsed by the owner of ApexCharts. The name is used here only to describe compatibility and to credit the origin of the code (see
LICENSEandNOTICE).
Which versions? This guide is written for code that targets ApexCharts 4.x (4.0 to 4.7). Options that first appeared in later ApexCharts versions are not part of WestCoast Charts.
- The switch in three steps
- What stays the same
- What behaves differently – read this before you ship
- What is new
- Checklist
The switch in three steps
1. Replace the package.
npm uninstall apexcharts
npm install west-coast-charts@1.1.52. Change the import. The default export is the chart class. It is also exported under the name
ApexCharts, so the rest of your code can keep the old identifier:
// before: import ApexCharts from 'apexcharts'
import { ApexCharts } from 'west-coast-charts'
const chart = new ApexCharts(document.querySelector('#chart'), {
chart: { type: 'area', height: 300 },
series: [{ name: 'Sign-ups', data: [31, 40, 28, 51, 42, 109, 100] }],
xaxis: { categories: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7'] },
})
await chart.render()With script tags, swap the file. The bundle defines the global WestCoastCharts and also
window.ApexCharts when that global is still free, so inline code that says new ApexCharts(...)
keeps working:
<!-- before: <script src=".../apexcharts.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/west-coast-charts@1.1.5/dist/west-coast-charts.min.js"></script>
<div id="chart"></div>
<script>
new ApexCharts(document.querySelector('#chart'), {
chart: { type: 'bar', height: 260 },
series: [{ name: 'Tickets', data: [8, 13, 5, 21] }],
xaxis: { categories: ['Mon', 'Tue', 'Wed', 'Thu'] },
}).render()
</script>3. Decide about the look. Charts use the new coastal theme preset by default (palette, typography,
spacing). To keep the 4.7.0 appearance pixel for pixel, select the classic preset, either per chart or
for every chart through the window.Apex global defaults, which work as before:
import WestCoastCharts from 'west-coast-charts'
// every chart on the page
window.Apex = { theme: { preset: 'classic' } }
// or one chart
const chart = new WestCoastCharts(document.querySelector('#chart'), {
theme: { preset: 'classic' },
chart: { type: 'line', height: 260 },
series: [{ name: 'Errors', data: [3, 1, 4, 1, 5] }],
})
await chart.render()
console.log(chart.w.globals.colors[0]) // '#008FFB', the 4.7.0 paletteThen run your test suite and go through What behaves differently.
What stays the same
| Area | Status |
|---|---|
| Options | Familiar 4.7.0 option names and structure; review the behaviour and default changes documented below |
| Chart types | All 4.7.0 types are in the core: line, area, bar/column, rangeBar, rangeArea, candlestick, boxPlot, scatter, bubble, heatmap, treemap, pie, donut, polarArea, radar, radialBar, mixed charts |
| Methods | render, updateOptions, updateSeries, appendSeries, appendData, toggleSeries, showSeries, hideSeries, resetSeries, zoomX, toggleDataPointSelection, addXaxisAnnotation and the other annotation methods, dataURI, destroy, and the static exec, getChartByID, merge, initOnLoad |
| Events | chart.events.* callbacks with the same arguments |
| Global defaults | window.Apex |
| Locales | The same locale objects and chart.locales / chart.defaultLocale |
| CSS | Every apexcharts-* class name stays, so your style overrides and test selectors keep matching. The root element also gets the class wcc |
| TypeScript | ApexOptions and all Apex* types are still exported |
The complete, generated list is in the options reference and the methods reference.
What behaves differently
These changes are deliberate: they fix security issues or crashes, or they add accessibility. Each one names the setting that restores the 4.7.0 behaviour where one exists.
1. Default theme
New charts use the coastal preset. Use theme: { preset: 'classic' } for the old look
(step 3). Explicit colours, fonts and theme.palette settings are applied
on top of either preset, as before. See docs/THEMING.md (library repository).
2. HTML in labels, legends and tooltips
- Strings from data and configuration (series names, categories, labels, titles, annotation text,
locale strings) are always drawn as text. A series named
<b>EU</b>shows those characters instead of bold text. - HTML returned by your functions (formatters,
tooltip.custom,legend.markers.customHTML) and explicit markup options (toolbar icons,customSVG) is still allowed, but it passes through a sanitizer first. Event-handler attributes,javascript:URLs and scripts are removed. chart.sanitizeHtmlcontrols this:true(default, built-in allow-list), a function(html, { svg }) => string | Nodeto plug in your own sanitizer such as DOMPurify, orfalsefor rawinnerHTMLas in 4.7.0 (only for output you fully trust).- When you build HTML from data in a formatter, escape the data with
WestCoastCharts.escapeHtml().
import WestCoastCharts from 'west-coast-charts'
const chart = new WestCoastCharts(document.querySelector('#chart'), {
chart: { type: 'line', height: 260 },
series: [
{ name: 'eu-west', data: [12, 18, 15] },
{ name: 'us-east', data: [20, 14, 22] },
],
legend: {
show: true,
// escape the data, keep your own markup; the onerror handler is stripped by the sanitizer
formatter: (name) => `<b>${WestCoastCharts.escapeHtml(name)}</b><img src="x" onerror="alert(1)">`,
},
})
await chart.render()3. CSV export
exportToCSV neutralises spreadsheet formulas: text cells that start with =, +, -, @, tab or
carriage return get a leading '. Real numbers such as -12.5 are left alone. Cells containing the
delimiter, quotes or line breaks are quoted (RFC 4180) instead of having characters removed. There is no
switch back; this closes a formula-injection hole.
4. Malformed options no longer throw
Inputs that made 4.7.0 throw a TypeError, for example series: null, null entries in series,
data: null, xaxis.categories: null or annotations: null, are treated as empty, in the constructor
and in every update method. If your code relied on a throw to detect bad data, validate the data
yourself instead. Valid options are passed through untouched.
import WestCoastCharts from 'west-coast-charts'
const chart = new WestCoastCharts(document.querySelector('#chart'), {
chart: { type: 'bar', height: 240 },
series: null, // data not loaded yet: an empty chart instead of an exception
})
await chart.render()
await chart.updateSeries([{ name: 'Orders', data: [5, null, 9] }, null])5. Accessibility is on by default
Every chart now adds:
tabindex="0", an ARIA accessible name and<desc>on the chart SVG, plus keyboard navigation (arrow keys, Home/End, Enter/Space, zoom and pan keys). Tab is never captured.- a polite live region that announces the focused point, selection and zoom,
- a visually hidden data table for screen readers,
prefers-reduced-motionsupport: animations are skipped for users who ask for less motion.
This changes the DOM: snapshot tests and selectors that count elements inside the chart container, or tests of the page's tab order, can need an update. You can switch the parts off individually, but please only do so when you provide the same information another way:
import WestCoastCharts from 'west-coast-charts'
const chart = new WestCoastCharts(document.querySelector('#chart'), {
chart: {
type: 'line',
height: 240,
accessibility: {
enabled: true, // master switch
keyboard: { enabled: true },
announcements: { enabled: true },
},
animations: { respectReducedMotion: true },
},
wcc: { a11y: { dataTable: false } }, // 'hidden' (default) | 'details' (visible) | false
series: [{ name: 'Queue depth', data: [4, 9, 6, 12] }],
})
await chart.render()Details: docs/ACCESSIBILITY.md (library repository).
6. Bundle size
The core is larger than ApexCharts 4.7.0 because the accessibility, security, theming and robustness
work above lives in it: 192,030 B against 152,686 B for apexcharts.min.js 4.7.0 (gzip level 9, measured
on integrate/v1 d03e23b2). Where the bytes go is documented in
docs/architecture/size-ledger.md (library repository). New chart types and features live in
separate entries, so they cost nothing unless you import them.
7. Unknown chart types fail loudly
If chart.type names a WestCoast Charts type whose entry is not loaded (for example funnel without
west-coast-charts/types), render() rejects with a message naming the import to add, and logs the same
hint. Types that existed in 4.7.0 are never affected.
8. Toolbar size in the new presets
The coastal preset (and the presets from west-coast-charts/types/themes) uses 28 × 28 px toolbar
buttons to meet the WCAG 2.5.8 target size. classic keeps the 4.7.0 20 px icons.
9. Browser support
The core still targets ES2018 engines (Chrome 60+, Edge 79+, Firefox 55+, Safari 11.1+). Optional feature bundles and the premium bundle need ES2020; see Getting started and the browser table in the repository README.
What is new
Everything below is optional; none of it changes a 4.7.0 configuration.
| Addition | Where | Docs |
|---|---|---|
Theme presets coastal and classic in the core; midnight, paper, accessible and colour-vision palettes (theme.accessibility.colorBlindMode) |
core, west-coast-charts/types/themes |
THEMING.md (library repository) |
| 14 additional chart types: gauge, funnel/pyramid, waterfall, dumbbell, histogram, violin/raincloud, sunburst, icicle, streamgraph, unit/waffle, barRace, calendar, slope, beeswarm (plus nested treemaps and box plots from raw samples) | west-coast-charts/types or west-coast-charts/types/<name> |
options reference |
| Keyboard navigation, announcements, data table, focus ring | core | ACCESSIBILITY.md (library repository) |
Large-data rendering: dense-mark paths and line/area decimation (wcc.performance), optional canvas renderer |
core (dense marks), west-coast-charts/types/decimate, west-coast-charts/features/renderer-canvas |
Performance and security |
| Label readability (halo, pill, auto contrast) | west-coast-charts/features/readability |
docs/features/readability.md (library repository) |
| Drill-down, linked charts, highlight and filter, undo history, narrative captions, perspectives, storyboards, trellis small multiples | west-coast-charts/features/<name> |
docs/features/ |
Plugin API: WestCoastCharts.use(plugin) |
core | docs/architecture/plugins.md (library repository) |
WestCoastCharts.escapeHtml, chart.sanitizeHtml, Trusted Types policy west-coast-charts |
core | Performance and security |
| Premium types: sankey, chord, gantt, tree, stock, map, marimekko, network, radialColumn | west-coast-charts/premium (licence key) |
Premium and licensing |
Checklist
-
apexchartsreplaced bywest-coast-chartsinpackage.jsonand in all imports or script tags - Look decided:
coastal(new default) ortheme: { preset: 'classic' } - Formatters that return HTML built from data use
WestCoastCharts.escapeHtml() - Series names or labels that contained intended HTML moved into a formatter
- Snapshot and DOM tests updated for the accessibility elements
- CSV consumers are fine with the
'prefix on formula-like cells - Code that relied on exceptions for bad configs now validates its data
- Content Security Policy checked (Getting started)
WestCoast Charts 1.1.5 · generated from the library guide at commit 95f093ba. Code examples in the guide are executed by the library's docs check.