Examples
Every working example of active-charts on one page, each at the width a chart needs, with the file that renders it.
@workspace/active-charts 6.0.0Status unknowncontent differs from the recorded release 6.0.0baseline ce081dc3
All examples are Client examples: the data is fixed and everything runs in your browser. Each one takes the full width of the page; open it in full screen, or on a page of its own, for more room. The settings of an example belong to it and sit with its chart; the code is one tab away.
The smallest chart#
A presentation and a translator once, one line for one series. The x values are calendar days, so
the axis says so (temporal): no time zone moves a point to another day.
// apps/docs/examples/charts/first-chart.tsx'use client';
import { ChartDefaults, englishChartTranslator, LineChart,} from '@workspace/active-charts';
const data = [ {date: new Date(Date.UTC(2026, 0, 2)), price: 100.5}, {date: new Date(Date.UTC(2026, 0, 5)), price: 101.2}, {date: new Date(Date.UTC(2026, 0, 6)), price: 102.0}, {date: new Date(Date.UTC(2026, 0, 7)), price: 101.4}, {date: new Date(Date.UTC(2026, 0, 8)), price: 103.1}, {date: new Date(Date.UTC(2026, 0, 9)), price: 104.0},];
/** The smallest chart: a presentation and a translator once, a line per series. */export default function FirstChart() { return ( <ChartDefaults locale="en-GB" t={englishChartTranslator}> <LineChart data={data} xKey="date" yKey="price" name="Price" // The x values are calendar days, not moments in time. xAxis={{temporalSemantic: 'calendarDate'}} height={260} /> </ChartDefaults> );}Every family#
Choose a family to draw it with small fixed data. The props that shape each archetype (cartesian, categorical, hierarchical, flow) are on Families.
// apps/docs/examples/charts/families.tsx'use client';
import {useState, type ReactNode} from 'react';import { BEFORE_AFTER, DAILY_PRICES, DELIVERY_DAYS, DELIVERY_SPREAD, FLOW_LINKS, FLOW_NODES, FUNNEL, MILESTONES, MONTHLY_SALES, ORGANISATION, PRICE_VS_RATING, PRODUCT_TREE, PROFIT_BRIDGE, SALES_SERIES, SHARE_BY_REGION, SKILL_SERIES, SKILLS, TEMPERATURE_BAND, WEEKDAY_ORDERS,} from '@/lib/examples/chart-data';
import { AreaChart, BarChart, BoxPlotChart, BulletChart, CandlestickChart, ChartDefaults, DumbbellChart, englishChartTranslator, FunnelChart, GaugeChart, HeatmapChart, Histogram, LinearGauge, LineChart, LollipopChart, NightingaleChart, OhlcChart, OrgChart, PieChart, RadarChart, RadialBarChart, RangeAreaChart, RangeBarChart, SankeyChart, ScatterChart, Sparkline, SunburstChart, TimelineChart, TreemapChart, WaterfallChart,} from '@workspace/active-charts';import { Field, FieldLabel,} from '@workspace/active-ui/components/primitives/field';import { NativeSelect, NativeSelectOptGroup, NativeSelectOption,} from '@workspace/active-ui/components/primitives/native-select';
const H = 280;const PRICE = {kind: 'price', currency: 'EUR', decimals: 2} as const;
/** Every public chart family, grouped by the archetype that shapes its props. */const FAMILIES: Record<string, Record<string, () => ReactNode>> = { Cartesian: { Line: () => ( <LineChart data={MONTHLY_SALES} xKey="month" xAxis="category" series={SALES_SERIES} legend height={H} /> ), Area: () => ( <AreaChart data={MONTHLY_SALES} xKey="month" xAxis="category" series={SALES_SERIES} stacked legend height={H} /> ), Bar: () => ( <BarChart data={MONTHLY_SALES} xKey="month" xAxis="category" series={SALES_SERIES} legend height={H} /> ), Histogram: () => ( <Histogram data={DELIVERY_DAYS} xKey="days" name="Orders" binCount={8} height={H} /> ), Scatter: () => ( <ScatterChart data={PRICE_VS_RATING} xKey="price" xAxis={{type: 'number', title: 'Price'}} yKey="rating" name="Products" yAxis={{title: 'Rating'}} height={H} /> ), Candlestick: () => ( <CandlestickChart data={DAILY_PRICES} xKey="date" xAxis={{temporalSemantic: 'calendarDate'}} openKey="open" highKey="high" lowKey="low" closeKey="close" name="Price" yAxis={{valueSemantics: PRICE}} height={H} /> ), OHLC: () => ( <OhlcChart data={DAILY_PRICES} xKey="date" xAxis={{temporalSemantic: 'calendarDate'}} openKey="open" highKey="high" lowKey="low" closeKey="close" name="Price" yAxis={{valueSemantics: PRICE}} height={H} /> ), 'Range area': () => ( <RangeAreaChart data={TEMPERATURE_BAND} xKey="month" xAxis="category" yLowKey="low" yHighKey="high" name="Temperature" height={H} /> ), 'Range bar': () => ( <RangeBarChart data={TEMPERATURE_BAND} xKey="month" xAxis="category" yLowKey="low" yHighKey="high" name="Temperature" height={H} /> ), 'Box plot': () => ( <BoxPlotChart data={DELIVERY_SPREAD} xKey="carrier" xAxis="category" minKey="min" q1Key="q1" medianKey="median" q3Key="q3" maxKey="max" outliersKey="out" name="Delivery days" height={H} /> ), Dumbbell: () => ( <DumbbellChart data={BEFORE_AFTER} xKey="team" xAxis="category" yLowKey="before" yHighKey="after" lowName="2025" highName="2026" height={H} /> ), Lollipop: () => ( <LollipopChart data={MONTHLY_SALES} xKey="month" xAxis="category" yKey="online" name="Online" height={H} /> ), Waterfall: () => ( <WaterfallChart data={PROFIT_BRIDGE} xKey="step" yKey="amount" kindKey="kind" name="Profit" height={H} /> ), Heatmap: () => ( <HeatmapChart data={WEEKDAY_ORDERS} xKey="day" yKey="part" colorKey="orders" name="Orders" label={{enabled: true}} height={H} /> ), }, Categorical: { Pie: () => ( <PieChart data={SHARE_BY_REGION} valueKey="value" categoryKey="region" name="Share" legend height={H} /> ), Funnel: () => ( <FunnelChart data={FUNNEL} valueKey="count" categoryKey="stage" name="Visitors" height={H} /> ), 'Radial bar': () => ( <RadialBarChart data={SHARE_BY_REGION} valueKey="value" categoryKey="region" name="Share" height={H} /> ), Nightingale: () => ( <NightingaleChart data={SHARE_BY_REGION} valueKey="value" categoryKey="region" name="Share" legend height={H} /> ), Radar: () => ( <RadarChart data={SKILLS} categoryKey="skill" series={SKILL_SERIES} min={0} max={10} legend height={H} /> ), }, 'Hierarchy and flow': { Treemap: () => <TreemapChart data={PRODUCT_TREE} height={H} />, Sunburst: () => <SunburstChart data={PRODUCT_TREE} height={H} />, Sankey: () => ( <SankeyChart nodes={FLOW_NODES} links={FLOW_LINKS} height={H} /> ), 'Organisation chart': () => ( <OrgChart data={ORGANISATION} direction="horizontal" height={320} /> ), Timeline: () => <TimelineChart data={MILESTONES} height={220} />, }, Scalar: { Gauge: () => ( <GaugeChart value={72} min={0} max={100} zones={[ {from: 0, to: 40, color: 'var(--chart-negative)', label: 'low'}, {from: 40, to: 75, color: 'var(--chart-caution)', label: 'fair'}, {from: 75, to: 100, color: 'var(--chart-positive)', label: 'good'}, ]} label="Satisfaction" height={220} /> ), 'Linear gauge': () => ( <LinearGauge value={68} min={0} max={100} target={75} label="Budget used (%)" height={120} /> ), Bullet: () => ( <BulletChart value={82} min={0} max={120} target={100} label="Orders vs target" height={90} /> ), Sparkline: () => ( <Sparkline data={MONTHLY_SALES.map((row) => row.online)} width={220} height={48} type="area" showLastPoint /> ), },};
const ALL = Object.entries(FAMILIES).flatMap(([group, members]) => Object.keys(members).map((name) => ({group, name})),);
/** The public chart families, each with small fixed data; pick one to draw it. */export default function ChartFamilies() { const [choice, setChoice] = useState('Cartesian/Line'); const [group, name] = choice.split('/') as [string, string]; const render = FAMILIES[group]![name]!; return ( <div className="flex w-full flex-col gap-4"> <Field className="max-w-xs"> <FieldLabel htmlFor="chart-family">Chart family</FieldLabel> <NativeSelect id="chart-family" className="w-full" value={choice} onChange={(event) => setChoice(event.target.value)} > {Object.keys(FAMILIES).map((g) => ( <NativeSelectOptGroup key={g} label={g}> {ALL.filter((entry) => entry.group === g).map((entry) => ( <NativeSelectOption key={entry.name} value={`${g}/${entry.name}`} > {entry.name} </NativeSelectOption> ))} </NativeSelectOptGroup> ))} </NativeSelect> </Field> <ChartDefaults locale="en-GB" t={englishChartTranslator}> <div key={choice} data-chart-family={choice}> {render()} </div> </ChartDefaults> </div> );}Selection, tooltip, legend and export#
Hover for the shared tooltip, select bars with a click or the keyboard (arrow keys, then Space), and export the data or an image through the chart's handle. The line below the buttons reads the selection back; the export reports its file name and size. How each format works: Export.
Selected: nothing
// apps/docs/examples/charts/interaction.tsx'use client';
import {useRef, useState} from 'react';import {MONTHLY_SALES, SALES_SERIES} from '@/lib/examples/chart-data';
import { BarChart, englishChartTranslator, type ChartHandle, type ChartItemRef,} from '@workspace/active-charts';import {Button} from '@workspace/active-ui/components/primitives/button';
/** A readable name for a selected bar: its series and its month. */function describe(ref: ChartItemRef): string { if ('seriesId' in ref) return `${ref.seriesId} @ ${String(ref.key)}`; return JSON.stringify(ref);}
/** * Selection under the host's control, the shared tooltip and legend, and * the export of the imperative handle. Click a bar, or move to it with the * arrow keys and press Space, to select it; Shift+F10 opens the chart's menu * with copy, the data table and export. */export default function ChartInteraction() { const chart = useRef<ChartHandle>(null); const [selected, setSelected] = useState<ChartItemRef[]>([]); const [exported, setExported] = useState<string | null>(null); return ( <div className="flex w-full flex-col gap-4"> <BarChart ref={chart} data={MONTHLY_SALES} xKey="month" xAxis="category" series={SALES_SERIES} legend tooltip={{enabled: true, mode: 'shared'}} selection selectedItems={selected} onSelectionChange={(next) => setSelected(next)} height={300} locale="en-GB" t={englishChartTranslator} /> <div className="flex flex-wrap items-center gap-2"> <Button variant="outline" size="sm" onClick={async () => { const result = await chart.current?.exportAsCsv('sales.csv'); setExported( result ? `${result.filename}: ${result.blob.size} bytes` : null, ); }} > Export CSV </Button> <Button variant="outline" size="sm" onClick={async () => { const result = await chart.current?.exportAsPng('sales.png', 2); setExported( result ? `${result.filename}: ${result.blob.size} bytes` : null, ); }} > Export PNG </Button> <Button variant="ghost" size="sm" disabled={selected.length === 0} onClick={() => setSelected([])} > Clear selection </Button> </div> <p className="text-sm" aria-live="polite" data-chart-selection> Selected:{' '} {selected.length > 0 ? selected.map(describe).join(', ') : 'nothing'} </p> {exported ? ( <p className="text-muted-foreground text-sm">{exported}</p> ) : null} </div> );}Data a chart cannot draw#
No rows, a gauge whose range is empty, a flow that loops: a chart shows a translated unavailable state instead of an empty frame or a drawing that misleads. Interaction and states explains when each state appears.
No rows
Empty gauge range
A flow with a loop
// apps/docs/examples/charts/states.tsx'use client';
import { BarChart, ChartDefaults, englishChartTranslator, GaugeChart, SankeyChart,} from '@workspace/active-charts';
/** * What a chart shows when it cannot draw the data truthfully: no rows, a * gauge whose range is empty, a flow that loops. Each is a translated * unavailable state, not an empty frame or a broken drawing. */export default function ChartStates() { return ( <ChartDefaults locale="en-GB" t={englishChartTranslator}> <div className="grid w-full gap-6 sm:grid-cols-3"> <section aria-label="No rows" data-chart-state="empty"> <p className="mb-2 text-sm font-medium">No rows</p> <BarChart data={[]} xKey="month" xAxis="category" yKey="sales" name="Sales" height={180} /> </section> <section aria-label="Empty range" data-chart-state="range"> <p className="mb-2 text-sm font-medium">Empty gauge range</p> <GaugeChart value={5} min={10} max={10} label="Score" height={180} /> </section> <section aria-label="A loop" data-chart-state="cycle"> <p className="mb-2 text-sm font-medium">A flow with a loop</p> <SankeyChart nodes={[ {id: 'a', label: 'A'}, {id: 'b', label: 'B'}, ]} links={[ {source: 'a', target: 'b', value: 3}, {source: 'b', target: 'a', value: 1}, ]} height={180} /> </section> </div> </ChartDefaults> );}