amCharts 5 Integration

MAIDR ships an amCharts 5 binder. The recommended entry point, bindAmCharts(root), mounts MAIDR over a rendered amCharts 5 XYChart and adds audio sonification, text descriptions, braille output, keyboard navigation, and a visual highlight overlay on the active data point. A lower-level fromAmCharts(root) returns plain MAIDR JSON (no highlighting) for the maidr attribute or the <Maidr> React component.

Note: amCharts 5 is a commercial charting library and is not bundled with MAIDR — load it yourself. amCharts 4 has a different API and is not supported. The MAIDR amCharts adapter ships as both a UMD bundle (dist/amcharts.js, exposing the maidrAmCharts global for plain <script> tags) and an ES module (dist/amcharts.mjs, for bundlers via import 'maidr/amcharts').

Quick Start

Load amCharts 5 and MAIDR core, build your chart as usual, then convert it once it has rendered:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My amCharts 5 Chart</title>
    <!-- 1. Load amCharts 5 (core + XY) -->
    <script src="https://cdn.amcharts.com/lib/5/index.js"></script>
    <script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
    <!-- 2. Load the MAIDR amCharts adapter (UMD; bundles MAIDR + React) -->
    <script src="https://cdn.jsdelivr.net/npm/maidr/dist/amcharts.js"></script>
  </head>
  <body>
    <div id="chartdiv" style="width: 600px; height: 400px"></div>

    <!-- 3. Build the chart -->
    <script>
      var root = am5.Root.new("chartdiv");
      var chart = root.container.children.push(am5xy.XYChart.new(root, {}));
      var xAxis = chart.xAxes.push(
        am5xy.CategoryAxis.new(root, { categoryField: "day", renderer: am5xy.AxisRendererX.new(root, {}) })
      );
      var yAxis = chart.yAxes.push(
        am5xy.ValueAxis.new(root, { renderer: am5xy.AxisRendererY.new(root, {}) })
      );
      var series = chart.series.push(
        am5xy.ColumnSeries.new(root, {
          name: "Tips", xAxis: xAxis, yAxis: yAxis, valueYField: "count", categoryXField: "day",
        })
      );
      var data = [
        { day: "Sat", count: 87 }, { day: "Sun", count: 76 },
        { day: "Thur", count: 62 }, { day: "Fri", count: 19 },
      ];
      xAxis.data.setAll(data);
      series.data.setAll(data);
    </script>

    <!-- 4. After the chart renders, mount MAIDR with canvas highlighting. -->
    <script>
      // amCharts validates data asynchronously; in production listen to a
      // series' "datavalidated" event instead of a fixed timeout.
      setTimeout(function () {
        maidrAmCharts.bindAmCharts(root, {
          title: 'Number of Tips by Day',
          axisLabels: { x: 'Day', y: 'Count' },
        });
      }, 1000);
    </script>
  </body>
</html>

Once bound, click the chart (or Tab to it) and MAIDR activates with audio, text, braille, arrow-key navigation, and a highlight box drawn on the active data point.

How It Works

There are two entry points:

Both walk the chart's series, classify each one, and extract its data into MAIDR's schema. Each series becomes a layer; all line series merge into a single multi-line layer. If no chart contains a supported series with data, both entry points throw a descriptive error — bind after your data has been set (see the datavalidated note in the Quick Start).

Series are classified by their amCharts class name and field configuration:

Visual Highlighting

amCharts 5 renders to an HTML5 <canvas>, so there are no per-element SVG nodes for MAIDR's usual highlighting. bindAmCharts instead draws an absolutely-positioned outline box over the canvas at the active data point's pixel geometry (computed via am5's sprite.toGlobal()) — the same overlay approach the Chart.js adapter uses. The overlay re-anchors on resize. Call the returned dispose() to unmount MAIDR, remove the overlay, and restore the chart. Highlighting is unavailable on the fromAmCharts JSON/attribute path.

Supported Chart Types

Chart Type amCharts 5 series Detection signal
Bar / Column ColumnSeries (single) category axis + value axis
Dodged / Grouped Bar multiple ColumnSeries no stacked flag
Stacked Bar multiple ColumnSeries stacked: true
100% Stacked (Normalized) multiple ColumnSeries stacked: true + valueYShow: "valueYTotalPercent"
Line (single & multi-series) LineSeries line series class
Histogram ColumnSeries value X axis + openValueXField bin edges
Heatmap ColumnSeries category X and category Y axes + value field

Box plots, candlestick, scatter, violin, and smooth/regression layers are not supported by the amCharts binder. amCharts 5 has no dedicated scatter or box series, and there is no reliable runtime signal to distinguish a scatter (hidden-stroke LineSeries) from a normal line chart.

Multi-Panel Charts

When one amCharts Root contains multiple XYCharts — amCharts' native multi-panel pattern (root.container.set("layout", root.verticalLayout) plus several XYChart children, or a horizontalLayout/GridLayout) — both bindAmCharts and fromAmCharts convert each chart into its own MAIDR subplot. The same applies to am5stock StockChart panels (StockPanel extends XYChart), which the binder finds by walking the root's container tree; scrollbar preview charts (XYChartScrollbar) are excluded.

var root = am5.Root.new("chartdiv");
root.container.set("layout", root.verticalLayout);
var priceChart = root.container.children.push(am5xy.XYChart.new(root, { height: am5.percent(60) }));
var volumeChart = root.container.children.push(am5xy.XYChart.new(root, { height: am5.percent(40) }));
// ... axes, series, data for each chart ...
maidrAmCharts.bindAmCharts(root); // one MAIDR figure, two subplots

Details:

Stacked value axes within one XYChart (the classic price+volume single-chart pattern) are not split into panels — amCharts cannot reliably distinguish that layout from a dual-scale overlay, so all series stay in one subplot. Charts in separate Roots (one div each) remain separate MAIDR figures.

Code Examples

A complete, runnable page covering every supported type lives at examples/amcharts.html. The snippets below show the per-type series configuration; the surrounding root/chart/axis boilerplate and the fromAmCharts conversion are identical to the Quick Start.

Dodged / Grouped Bar

Multiple column series with no stacked flag render side-by-side and map to the DODGED trace type.

function addSeries(name, field) {
  var s = chart.series.push(am5xy.ColumnSeries.new(root, {
    name: name, xAxis: xAxis, yAxis: yAxis, valueYField: field, categoryXField: "city",
  }));
  s.data.setAll(data);
}
addSeries("2020", "y2020");
addSeries("2025", "y2025");

Stacked Bar

Add stacked: true to each column series; the binder maps these to the STACKED trace type.

chart.series.push(am5xy.ColumnSeries.new(root, {
  name: "Survived", stacked: true,
  xAxis: xAxis, yAxis: yAxis, valueYField: "survived", categoryXField: "class",
}));

100% Stacked (Normalized) Bar

stacked: true plus valueYShow: "valueYTotalPercent" produces a normalized chart (STACKED_NORMALIZED_BAR). Set calculateTotals: true on the value axis so amCharts can compute the percentages.

var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
  calculateTotals: true, min: 0, max: 100, renderer: am5xy.AxisRendererY.new(root, {}),
}));
chart.series.push(am5xy.ColumnSeries.new(root, {
  name: "Survived", stacked: true, valueYShow: "valueYTotalPercent",
  xAxis: xAxis, yAxis: yAxis, valueYField: "survived", categoryXField: "class",
}));

Multi-series Line

Each LineSeries becomes one line; the binder merges them into a single multi-line layer using the series names as group labels.

chart.series.push(am5xy.LineSeries.new(root, {
  name: "Sales", xAxis: xAxis, yAxis: yAxis, valueYField: "sales", categoryXField: "year",
}));
chart.series.push(am5xy.LineSeries.new(root, {
  name: "Expenses", xAxis: xAxis, yAxis: yAxis, valueYField: "expenses", categoryXField: "year",
}));

Histogram

amCharts 5 has no native histogram series. Use a ColumnSeries on a value X axis with openValueXField (bin start) and valueXField (bin end); the count goes in valueYField.

var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, { renderer: am5xy.AxisRendererX.new(root, {}) }));
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
  name: "Frequency", xAxis: xAxis, yAxis: yAxis,
  valueYField: "count", valueXField: "to", openValueXField: "from",
}));
series.data.setAll([
  { from: 0, to: 10, count: 4 }, { from: 10, to: 20, count: 11 },
  { from: 20, to: 30, count: 18 }, { from: 30, to: 40, count: 9 },
]);

Heatmap

A ColumnSeries with both a category X axis and a category Y axis forms a 2D grid; the binder reads the heat value from the value data field.

var xAxis = chart.xAxes.push(am5xy.CategoryAxis.new(root, { categoryField: "weekday", renderer: am5xy.AxisRendererX.new(root, {}) }));
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, { categoryField: "hour", renderer: am5xy.AxisRendererY.new(root, { inversed: true }) }));
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
  calculateAggregates: true, xAxis: xAxis, yAxis: yAxis,
  categoryXField: "weekday", categoryYField: "hour", valueField: "value",
}));

Keyboard Controls

Once a chart is focused, use the standard MAIDR shortcuts:

Function Key (Windows) Key (Mac)
Move between data points Arrow keys Arrow keys
Go to extremes Ctrl + Arrow Cmd + Arrow
Move between layers Page Up / Page Down Page Up / Page Down
Toggle Sonification S S
Toggle Braille Mode B B
Toggle Text Mode T T
Toggle Review Mode R R
Auto-play Ctrl + Shift + Arrow Cmd + Shift + Arrow
Stop Auto-play Ctrl Cmd

For the full list, see the Keyboard Controls reference.

npm Installation (Optional)

For bundler-based projects:

npm install maidr @amcharts/amcharts5
import { bindAmCharts } from 'maidr/amcharts';

// root: am5.Root — mounts MAIDR + canvas highlight overlay, returns a handle.
const binding = bindAmCharts(root, { title: 'Sales by Day' });
// later: binding.dispose();

bindAmCharts(root, options?) finds every XYChart in root.container (one subplot per chart — see Multi-Panel Charts); bindXYChart(chart, root, options?) takes a chart you already hold. Options accept title, subtitle, axisLabels: { x, y }, plus highlight (default true) and highlightColor. Pass { highlight: false } to mount the accessible UI without the overlay.

For the data-only path (no highlighting), use fromAmCharts(root, options?) / fromXYChart(chart, containerEl, options?), which return MAIDR JSON for the maidr attribute or <Maidr data={...}>.

API Documentation

For the complete TypeScript API reference, see the API Documentation.