Jerry Orta
← Blog

Charts as a Library, Not a Component

Most Angular charting starts the same way: a BarChartComponent, then a LineChartComponent, then a ScatterChartComponent — each with its own svg, its own axes, its own tooltip. Six charts in, you have six copies of the same layout math and no two that look alike. I wanted the opposite: one chart, many layers, configured with data.

One component, driven by a config

The whole surface is a single nge-chart element that takes one input — a plain ChartConfig you build from a preset factory. The component lays out the plot area, draws the shared axes, and hands each layer a render context. It knows nothing about bars or lines.

import { createBarChartConfig } from '@nge/charts';

config = createBarChartConfig({
  data: [
    { label: 'A', value: 30 },
    { label: 'B', value: 55 },
  ],
  tooltip: { enabled: true },
});

Layers compose

A layer is { type, data, renderer } — a pure D3 function that draws into the shared context. Because every layer shares one base layout and one set of scales, you stack them: bars under a line under a scatter, all on the same axes, by appending to config.layers. A new chart type is a render function, a config, a theme slice, and a preset — never another component wired into a central switch.

Why it scales

Styling rides a domain-agnostic --chart-* CSS-variable contract, so a chart is themeable without touching its code and every chart reads as one system. That's the payoff of a library over a pile of components: the tenth chart costs what the second one did. For the mechanics behind that — layer composition, tree-shaking, and the D3-driven tooltip — see the concept note Charts Library Architecture. More in the ngx-experiments overview.