Skip to content

Click events & drill-down

Every chart fires onClick (vanilla) / onPointClick (React) when the user clicks a hovered datum. The handler receives a third argument — a ChartClickEvent — with everything you need to identify what was clicked.

Click any bar with a mouse, or tap one on a touch device. The badge below the chart reports the label, value, modifier keys, and whether the input came from mouse or touch.

Click a bar (or tap on a touch device) — the result will appear here.
interface ChartClickEvent<TDatum = Record<string, any>> {
index: number; // datum index along the chart's primary axis
seriesIndex: number; // -1 when click is not series-specific
label: string; // categorical label at `index` (e.g. x-tick)
value: number; // numeric value at the clicked position
datum: TDatum | undefined; // the original row passed to setData()
series: Dataset | undefined;
data: ResolvedData; // same as the second positional argument
nativeEvent: MouseEvent; // for stopPropagation, modifier keys, coordinates
}

Use event.datum to navigate using the original row — no need to keep a parallel lookup.

import { Bar } from '@arshad-shah/swift-chart/react';
import { useRouter } from 'next/router';
export function RevenueByRegion({ orders }) {
const router = useRouter();
return (
<Bar
data={orders}
mapping={{ x: 'region', y: 'revenue' }}
onPointClick={(_i, _d, e) => {
if (!e.datum) return;
router.push(`/regions/${e.datum.id}`);
}}
/>
);
}

Open in a new tab on ⌘-click (or middle-click) instead of replacing the current view.

onPointClick={(_i, _d, e) => {
const url = `/orders/${e.datum.id}`;
if (e.nativeEvent.metaKey || e.nativeEvent.ctrlKey) {
window.open(url, '_blank');
} else {
router.push(url);
}
}}
onPointClick={(_i, _d, e) => {
analytics.track('chart_click', {
chart: 'revenue_by_region',
label: e.label,
value: e.value,
series: e.series?.label,
seriesIndex: e.seriesIndex,
});
}}

event.seriesIndex reports which series was clicked when the chart can pinpoint one:

ChartseriesIndex on click
Single-series (pie, treemap, gauge)0
Bubble / scatterthe group index — clicks land on a single point
Heatmapthe row (y-axis) index of the clicked cell
Marimekkothe row index of the clicked segment
Multi-series line / area / grouped-bar-1 — the click is column-wide, no single series is identified

When seriesIndex is -1, event.series is undefined and event.value is NaN — read event.label and event.data.datasets instead.

event.datum is the original row from setData(rows, mapping). It is undefined when:

  • the chart was fed a pre-built { labels, datasets } shape (the original row never existed)
  • the chart’s internal layout breaks index alignment (heatmap — read event.label and event.value instead)

Sankey and network charts surface the clicked node object as event.datum.

import { BarChart } from '@arshad-shah/swift-chart';
new BarChart('#chart', {
onClick: (index, data, event) => {
console.log('clicked', event.label, event.value, event.datum);
},
}).setData(orders, { x: 'region', y: 'revenue' });

A finger tap on a chart fires the same onClick / onPointClick handler with the index of the touched datum — event.nativeEvent is the synthetic MouseEvent that the browser dispatches after touchend, so modifier-key checks (metaKey, ctrlKey) read as false on touch. Use event.label, event.value, and event.datum for routing logic that needs to work on both pointers and touch.

The third argument is additive — existing two-argument handlers (index, data) => … keep working unchanged.