Annotations
Daily active users of a SaaS app from March to May 2025, in thousands. Callouts point at the days of two releases and at the worst day of a login outage, which moves when you randomize the data.
Pick a preset to reconfigure every chart
What to look for
- Text that wraps. A Unovis annotation is a text frame: give it a
width(here a fifth of the chart, in percent) and the text wraps inside it, so it narrows with the card. ECharts wraps a label at a fixedwidthwithoverflow: 'break', AG Charts at a series label'smaxWidth, Observable Plot at alineWidthin ems, and Recharts at a label'swidth. Chart.js, Vega-Lite and TanStack Charts don't wrap text: the demos break each callout into lines by hand. - Connectors. Unovis draws the connector from the edge of the text to the subject, with a gap around the point. The
others draw it as a mark of its own: a
markLinesegment in ECharts, aReferenceLinesegmentin Recharts, a two-point line series in AG Charts, a rule or link in Plot, Vega-Lite and TanStack Charts. The Chart.js annotation plugin has acallouton its labels; the label is lifted to its row with a pixelyAdjustthat a scriptable option computes from the y scale. - Randomize the data. The outage moves and every callout follows its point. The Unovis subjects are functions of the chart's scales, so they're placed again on every render and resize.
- Nivo has no annotations on line charts. Its
markersdraw a line across the whole plot at a value, with one line of text, so the demo marks the three days with vertical text instead of callouts. - AG Charts Community has no annotations: its Annotations module is Enterprise. Each callout is a line series of two points, from the day's value up to the callout row, and the text is the label of its top point.
- Presets. Rings (
subject.radius,connectorLineStrokeDasharray) puts a ring around each annotated day and dashes the connectors; the other libraries draw the rings as point or dot marks of their own. Nivo draws a point on every day, so only the event days' points get a border, from apointBorderColorfunction. Rich text (contentas a list of styled text blocks) sets a bold headline over the detail. ECharts does it in one label withrichstyles, Chart.js with afontper line and AG Charts with text segments from a labelformatter; Recharts, Plot, Vega-Lite and TanStack Charts take one weight per mark or label, so the headline is a second mark at a hand-set offset above the detail, and Recharts keeps the detail on one line to know where it ends. Incident window (VisPlotband,VisPlotline) shades the outage days and adds a goal line, which Nivo can't do without a custom layer.
Feature comparison
| Feature | Unovis1.8.0 | Recharts3.10.1 | Chart.js4.5.1 | ECharts6.1.0 | Nivo0.99.0 | AG Charts14.2.0 | Observable Plot0.6.17 | Vega-Lite6.5.0 | TanStack Charts1.1.0 |
|---|---|---|---|---|---|---|---|---|---|
| Annotations | |||||||||
| Reference lines | |||||||||
| Reference bands | |||||||||
| Crosshair with a shared tooltip | |||||||||
| Animated data updates | |||||||||
| Dark mode |
Every cell links to its source. See how we compare for the rules we followed.