Going further
Custom ECharts options
The option prop passes any ECharts setting to a component. When no component fits, the Chart component renders a raw ECharts option.
There are three ways to go beyond a component's props. They are listed from the smallest change to the largest.
The option prop
Every chart accepts option. As an object it is deep-merged over the option the component generated. As a function it receives that option and the build context and returns the option to draw.
Option as an object
Option as a function
import { BarChart } from "insightcharts";
const data = [
{ plan: "Free", accounts: 18400 },
{ plan: "Team", accounts: 6200 },
{ plan: "Business", accounts: 1900 },
{ plan: "Enterprise", accounts: 240 },
];
export default function OptionEscape() {
return (
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))", gap: 28 }}>
{/* An object is deep-merged over the generated option: here it patches the first series and the value axis. */}
<BarChart data={data} x="plan" y="accounts" orientation="vertical" format="compact" height={240} title="Option as an object" option={{ series: [{ barWidth: 36, itemStyle: { borderRadius: 0 } }], yAxis: { splitLine: { show: false } } }} />
{/* A function receives the generated option and the build context, and returns the option to draw. */}
<BarChart
data={data}
x="plan"
y="accounts"
orientation="vertical"
format="compact"
height={240}
title="Option as a function"
option={(option, ctx) => ({
...option,
graphic: [{ type: "text", right: 8, top: 8, style: { text: `${ctx.rows.length} plans · ${ctx.width}px wide`, fill: ctx.tokens.muted, fontSize: 12, fontFamily: ctx.tokens.fontFamily } }],
})}
/>
</div>
);
}
Merging follows the shape of the option:
- Plain objects merge key by key.
- An array of objects, such as
series, merges item by item:{ series: [{ smooth: true }] }patches the first series and leaves the rest alone. - A single object given where the option holds an array of objects is applied to every item:
{ series: { smooth: true } }patches all series. - Everything else (scalars, arrays of values) is replaced.
The context passed to the function form:
| Member | Contents |
|---|---|
rows | The data after loading, crossfilter and transform. |
tokens | The resolved theme. Every colour is a concrete value that canvas can draw. |
mode | "light" or "dark". |
width, height | Container size in CSS pixels. |
compact | True under 480 pixels wide. |
fmt, formatter(spec) | The value formatter from format, and a factory for others. |
color(key, index), dimmed(key), selected(value) | The same colour, highlight and selection helpers the component itself used. |
locale, animate | The active locale, and false when animation is off or the reader prefers reduced motion. |
option is applied last, after highlight and annotations.
The ECharts instance
onReady(chart) is called with the ECharts instance when it is created, and a ref exposes it later through getInstance(). onEvents binds ECharts events; prefix a name with zr: to listen on the canvas itself, which is how you listen for clicks on the blank area.
<BarChart
onEvents={{
click: (params) => console.log(params.name, params.value),
"zr:click": (event) => !event.target && console.log("blank area"),
}}
onReady={(chart) => chart.dispatchAction({ type: "showTip", seriesIndex: 0, dataIndex: 1 })}
...
/>Chart and Figure
When no component fits, render any ECharts option through Chart, the engine every component is built on. You still get lazy mounting, resizing, theme tokens, dark mode, reduced motion and export. Wrap it in Figure for the same title, subtitle and source line.
Current and new plan scores on five criteria
Internal scoring, 1 to 5
import { RadarChart } from "echarts/charts";
import { RadarComponent } from "echarts/components";
import { alpha, Chart, echarts, Figure } from "insightcharts";
// Series types outside the core set are registered once, exactly as in plain ECharts.
echarts.use([RadarChart, RadarComponent]);
const axes = ["Speed", "Reliability", "Docs", "Price", "Support"];
export default function ChartDirect() {
return (
<Figure title="Current and new plan scores on five criteria" subtitle="Internal scoring, 1 to 5" note="Illustrative data">
<Chart
height={300}
alt="Radar chart of two plans scored from 1 to 5 on five criteria. The new plan scores 5 on reliability, 4 on support and 2 on price. The current plan scores 3 on reliability, 2 on support and 4 on price."
option={({ tokens }) => ({
radar: {
indicator: axes.map((name) => ({ name, max: 5 })),
axisName: { color: tokens.inkSecondary },
splitLine: { lineStyle: { color: tokens.grid } },
axisLine: { lineStyle: { color: tokens.grid } },
splitArea: { show: false },
},
series: [
{
type: "radar",
symbolSize: 6,
data: [
{ name: "Current", value: [4, 3, 4, 4, 2], lineStyle: { color: tokens.context }, itemStyle: { color: tokens.context } },
{ name: "New", value: [4, 5, 4, 2, 4], lineStyle: { color: tokens.accent }, itemStyle: { color: tokens.accent }, areaStyle: { color: alpha(tokens.accent, 0.1) } },
],
},
],
})}
/>
</Figure>
);
}
option may be a full ECharts option or a function of the chart context, as here, so colours come from the theme and follow dark mode.
Already registered with ECharts: both renderers, the core components (grid, tooltip, dataset, transform, mark line, mark area, mark point, graphic, aria), label layout and universal transition. Anything else, such as the radar series above, is registered once with echarts.use([...]). Import echarts from insightcharts so you register on the same instance the library uses.
| Chart prop | Purpose |
|---|---|
option | An ECharts option, or (ctx) => option. |
height, aspect | CSS height (default 360), or width divided by height. |
renderer, markCount | "auto" picks canvas when markCount exceeds 1,500. |
theme, mode, animate, lazy, group | As on every chart. |
onEvents, onReady, onContext | Events, the instance, and the context each time an option is built. |
alt | Accessible description. |
exportMeta | Title, subtitle, source and rows for export. |
Your own components
If you need the same custom chart more than once, define a component for it. defineChart takes a pure build(props, ctx) function and returns a component with every feature described on this site: data loading, crossfilter, highlight, annotations, chrome, export and a JSON spec. The contributor guide in the repository (AGENTS.md) explains how, with atoms/bar-chart.tsx as the reference implementation.