---
id: "packages/active-charts/examples"
title: "Examples"
description: "Every working example of active-charts on one page, each at the width a chart needs, with the file that renders it."
url: "/packages/active-charts/examples"
locale: "en"
revision: "2f2cc65c182784f1"
---

# Examples

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 (`temporalSemantic: 'calendarDate'`): no time zone moves a point to another day.

**Example: A first chart**

Client: Runs entirely in your browser. Source: `examples/charts/first-chart.tsx`.

```tsx
// 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](/packages/active-charts/families).

**Example: Every chart family**

Client: Runs entirely in your browser. Source: `examples/charts/families.tsx`.

```tsx
// 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](/packages/active-charts/export).

**Example: Selection, tooltip, legend and export**

Client: Runs entirely in your browser. Source: `examples/charts/interaction.tsx`.

```tsx
// 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](/packages/active-charts/interaction-and-states) explains when each state
appears.

**Example: Data a chart cannot draw**

Client: Runs entirely in your browser. Source: `examples/charts/states.tsx`.

```tsx
// 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>
  );
}
```
