---
id: "packages/active-charts/families"
title: "Families"
description: "Every public chart family, drawn with small fixed data, and the props that shape each archetype."
url: "/packages/active-charts/families"
locale: "en"
revision: "dbc6726e4e9a3f25"
---

# Families

Choose a family to draw it. Each one is the public component with the props shown in the source;
the data is in [the example's data module](#the-data).

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

## Archetypes

Every chart takes `BaseChartProps` (size, title, tooltip, legend, context menu, animation,
accessibility, export) plus the props of its archetype:

| Archetype | Data props | Keyboard |
| --- | --- | --- |
| Cartesian | `data`, `xKey`, `yKey` or `series`, `xAxis`, `yAxis` | arrow keys along the series; Space selects |
| Categorical | `data`, `valueKey`, `categoryKey` | arrow keys between slices or bars |
| Hierarchical | `data`: one `HierarchyNode` (`label`, `value`, `children`) | arrow keys through the tree; drill down |
| Graph | `nodes` and `links` (sankey) | Enter switches between nodes and links |
| Scalar | `value`, `min`, `max`, `target`, `zones` | one stop with a full description |

The complete contract per family is in the [API reference](/packages/active-charts/api) and its
capabilities in [Capabilities](/packages/active-charts/capabilities).

## The data

`lib/examples/chart-data.ts`

```ts
// apps/docs/lib/examples/chart-data.ts

/**
 * Small, fixed datasets for the chart examples: a fictitious company's
 * sales, costs and organisation. Shapes follow the chart reference of the
 * lab the examples came from; the content is neutral and invented.
 */

export const MONTHLY_SALES = [
  {month: 'Jan', online: 42, stores: 61, costs: 70},
  {month: 'Feb', online: 45, stores: 58, costs: 68},
  {month: 'Mar', online: 51, stores: 63, costs: 74},
  {month: 'Apr', online: 49, stores: 66, costs: 77},
  {month: 'May', online: 56, stores: 64, costs: 79},
  {month: 'Jun', online: 61, stores: 69, costs: 83},
  {month: 'Jul', online: 58, stores: 72, costs: 81},
  {month: 'Aug', online: 63, stores: 70, costs: 85},
  {month: 'Sep', online: 67, stores: 75, costs: 88},
  {month: 'Oct', online: 71, stores: 77, costs: 90},
  {month: 'Nov', online: 78, stores: 81, costs: 96},
  {month: 'Dec', online: 92, stores: 88, costs: 104},
];

export const SALES_SERIES = [
  {yKey: 'online', name: 'Online'},
  {yKey: 'stores', name: 'Stores'},
];

/** Daily prices of one product over two weeks, as `Date` values. */
export const DAILY_PRICES = [
  [2, 101.2, 103.4, 100.8, 102.9],
  [3, 102.9, 104.1, 102.2, 103.6],
  [6, 103.6, 103.9, 101.5, 101.9],
  [7, 101.9, 102.8, 100.9, 102.5],
  [8, 102.5, 105.2, 102.3, 104.8],
  [9, 104.8, 106.0, 104.1, 105.1],
  [10, 105.1, 105.4, 103.2, 103.7],
  [13, 103.7, 104.6, 102.8, 104.2],
  [14, 104.2, 107.1, 104.0, 106.6],
  [15, 106.6, 107.3, 105.2, 105.9],
].map(([day, open, high, low, close]) => ({
  date: new Date(Date.UTC(2026, 6, day!)),
  open: open!,
  high: high!,
  low: low!,
  close: close!,
}));

export const SHARE_BY_REGION = [
  {region: 'North', value: 34},
  {region: 'East', value: 22},
  {region: 'South', value: 27},
  {region: 'West', value: 17},
];

export const DELIVERY_DAYS = [
  1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 8, 9, 12, 15,
].map((days) => ({days}));

export const PRICE_VS_RATING = [
  {product: 'A', price: 12, rating: 3.9, sold: 120},
  {product: 'B', price: 18, rating: 4.3, sold: 80},
  {product: 'C', price: 25, rating: 4.1, sold: 150},
  {product: 'D', price: 31, rating: 4.6, sold: 60},
  {product: 'E', price: 44, rating: 4.4, sold: 40},
  {product: 'F', price: 9, rating: 3.5, sold: 210},
];

export const WEEKDAY_ORDERS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'].flatMap(
  (day, d) =>
    ['Morning', 'Afternoon', 'Evening'].map((part, p) => ({
      day,
      part,
      orders: 20 + ((d * 7 + p * 11) % 23),
    })),
);

export const TEMPERATURE_BAND = MONTHLY_SALES.map((row, i) => ({
  month: row.month,
  low: 2 + Math.round(8 * Math.sin((i / 11) * Math.PI)),
  high: 8 + Math.round(14 * Math.sin((i / 11) * Math.PI)),
}));

export const DELIVERY_SPREAD = [
  {carrier: 'Carrier A', min: 1, q1: 2, median: 3, q3: 4, max: 7, out: [11]},
  {carrier: 'Carrier B', min: 1, q1: 3, median: 4, q3: 5, max: 8, out: []},
  {carrier: 'Carrier C', min: 2, q1: 3, median: 5, q3: 6, max: 9, out: [14]},
];

export const BEFORE_AFTER = [
  {team: 'Sales', before: 62, after: 71},
  {team: 'Support', before: 74, after: 79},
  {team: 'Product', before: 58, after: 66},
  {team: 'Finance', before: 69, after: 68},
];

export const SKILLS = [
  {skill: 'Speed', teamA: 7, teamB: 5},
  {skill: 'Quality', teamA: 6, teamB: 8},
  {skill: 'Cost', teamA: 5, teamB: 7},
  {skill: 'Service', teamA: 8, teamB: 6},
  {skill: 'Range', teamA: 4, teamB: 7},
];

export const SKILL_SERIES = [
  {valueKey: 'teamA', name: 'Team A'},
  {valueKey: 'teamB', name: 'Team B'},
];

export const FUNNEL = [
  {stage: 'Visited', count: 12000},
  {stage: 'Viewed a product', count: 5400},
  {stage: 'Added to basket', count: 1900},
  {stage: 'Ordered', count: 760},
];

export const PROFIT_BRIDGE = [
  {step: 'Revenue', amount: 820},
  {step: 'Cost of goods', amount: -410},
  {step: 'Staff', amount: -190},
  {step: 'Other costs', amount: -95},
  {step: 'Profit', amount: null, kind: 'total' as const},
];

export const PRODUCT_TREE = {
  label: 'Revenue',
  children: [
    {
      label: 'Hardware',
      children: [
        {label: 'Laptops', value: 210},
        {label: 'Phones', value: 160},
        {label: 'Accessories', value: 60},
      ],
    },
    {
      label: 'Services',
      children: [
        {label: 'Support', value: 120},
        {label: 'Training', value: 70},
      ],
    },
    {label: 'Software', children: [{label: 'Licences', value: 200}]},
  ],
};

export const ORGANISATION = {
  label: 'Managing director',
  meta: {title: 'Board'},
  children: [
    {
      label: 'Operations',
      meta: {title: 'Director'},
      children: [
        {label: 'Warehouse', meta: {title: 'Team'}},
        {label: 'Transport', meta: {title: 'Team'}},
      ],
    },
    {
      label: 'Commerce',
      meta: {title: 'Director'},
      children: [
        {label: 'Online sales', meta: {title: 'Team'}},
        {label: 'Stores', meta: {title: 'Team'}},
      ],
    },
  ],
};

export const FLOW_NODES = [
  {id: 'online', label: 'Online orders'},
  {id: 'stores', label: 'Store sales'},
  {id: 'revenue', label: 'Revenue'},
  {id: 'goods', label: 'Cost of goods'},
  {id: 'staff', label: 'Staff'},
  {id: 'profit', label: 'Profit'},
];

export const FLOW_LINKS = [
  {source: 'online', target: 'revenue', value: 380},
  {source: 'stores', target: 'revenue', value: 440},
  {source: 'revenue', target: 'goods', value: 410},
  {source: 'revenue', target: 'staff', value: 190},
  {source: 'revenue', target: 'profit', value: 220},
];

export const MILESTONES = [
  {date: '15 Jan 2026', label: 'Plan approved', category: 'Board'},
  {date: '3 Mar 2026', label: 'Supplier chosen', category: 'Operations'},
  {date: '12 May 2026', label: 'Pilot store', category: 'Commerce'},
  {date: '1 Sep 2026', label: 'Roll-out', category: 'Commerce'},
];
```
