Skip to main content

Charts

Forme includes five engine-native chart components that render directly to PDF vector graphics. Charts are processed by the Rust engine — no SVG intermediary, no external dependencies. The output is crisp at any zoom level and adds minimal file size.

Built-in chart components

import { BarChart, LineChart, PieChart, AreaChart, DotPlot } from '@formepdf/react';

BarChart

Simple category bar chart with optional grid, value labels, and title.
<BarChart
  width={400}
  height={200}
  data={[
    { label: 'Q1', value: 142000 },
    { label: 'Q2', value: 186000 },
    { label: 'Q3', value: 164000 },
    { label: 'Q4', value: 228000 },
  ]}
  color="#3b82f6"
  showLabels
  showValues
  showGrid
  title="Revenue by Quarter"
/>
PropTypeDefaultDescription
widthnumberChart width in points.
heightnumberChart height in points.
dataChartDataPoint[]Data points ({ label, value, color? }).
colorstring"#1a365d"Default bar color (hex). Per-item color overrides this.
showLabelsbooleantrueShow category labels on the X axis.
showGridbooleanfalseShow horizontal grid lines.
showValuesbooleanfalseShow value labels above each bar.
titlestringChart title displayed above the chart.

LineChart

Multi-series line chart with optional data points and grid.
<LineChart
  width={500}
  height={200}
  series={[
    { name: 'Active Users', data: [1200, 1800, 2400, 3100, 3800, 4200], color: '#3b82f6' },
    { name: 'New Signups', data: [400, 600, 800, 900, 1100, 1000], color: '#10b981' },
  ]}
  labels={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']}
  showPoints
  showGrid
  title="User Growth"
/>
PropTypeDefaultDescription
widthnumberChart width in points.
heightnumberChart height in points.
seriesChartSeries[]Series array ({ name, data: number[], color? }).
labelsstring[]X-axis labels (one per data point).
showPointsbooleanfalseShow dots at data points.
showGridbooleanfalseShow horizontal grid lines.
titlestringChart title.

PieChart

Pie or donut chart with optional legend.
<PieChart
  width={200}
  height={200}
  data={[
    { label: 'Subscriptions', value: 62, color: '#3b82f6' },
    { label: 'Enterprise', value: 28, color: '#0f172a' },
    { label: 'Services', value: 10, color: '#94a3b8' },
  ]}
  donut
  showLegend
  title="Revenue Split"
/>
PropTypeDefaultDescription
widthnumberChart width in points.
heightnumberChart height in points.
dataChartDataPoint[]Slices ({ label, value, color? }). Each slice should have a color.
donutbooleanfalseCut out the center to create a donut chart.
showLegendbooleanfalseShow a legend beside the chart.
titlestringChart title.

AreaChart

Multi-series area chart — like LineChart but with semi-transparent fill under each line.
<AreaChart
  width={500}
  height={200}
  series={[
    { name: 'Organic', data: [500, 800, 1200, 1800, 2600, 3200], color: '#3b82f6' },
    { name: 'Paid', data: [200, 400, 600, 900, 1100, 1400], color: '#f59e0b' },
    { name: 'Referral', data: [100, 150, 250, 400, 500, 600], color: '#10b981' },
  ]}
  labels={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']}
  showGrid
  title="Traffic Sources"
/>
PropTypeDefaultDescription
widthnumberChart width in points.
heightnumberChart height in points.
seriesChartSeries[]Series array ({ name, data: number[], color? }).
labelsstring[]X-axis labels.
showGridbooleanfalseShow horizontal grid lines.
titlestringChart title.

DotPlot

Scatter plot for (x, y) data with multiple groups and optional axis labels.
<DotPlot
  width={300}
  height={200}
  groups={[
    { name: 'API v1', color: '#3b82f6', data: [[10, 45], [50, 120], [100, 230]] },
    { name: 'API v2', color: '#10b981', data: [[10, 25], [50, 60], [100, 110]] },
  ]}
  xLabel="Concurrent Requests"
  yLabel="Latency (ms)"
  showLegend
  dotSize={3.5}
/>
PropTypeDefaultDescription
widthnumberChart width in points.
heightnumberChart height in points.
groupsDotPlotGroup[]Groups ({ name, color?, data: [x, y][] }).
xMin / xMaxnumberX-axis range (auto-computed if omitted).
yMin / yMaxnumberY-axis range (auto-computed if omitted).
xLabelstringX-axis label.
yLabelstringY-axis label.
showLegendbooleanfalseShow legend.
dotSizenumber4Dot radius in points.

Shared types

interface ChartDataPoint {
  label: string;
  value: number;
  color?: string;  // hex color, e.g. "#3b82f6"
}

interface ChartSeries {
  name: string;
  data: number[];
  color?: string;
}

interface DotPlotGroup {
  name: string;
  color?: string;
  data: [number, number][];  // [x, y] pairs
}
See the Components reference for the full prop tables.

Custom charts with SVG

For charts beyond what the built-in components offer, Forme renders SVG content via the <Svg> component. Any charting library that outputs SVG strings can be used to embed charts in your PDFs.

The pattern

  1. Use a charting library to produce an SVG string
  2. Pass the string to <Svg content={svgString} />
  3. Forme renders the SVG shapes directly into the PDF as vector graphics

D3 example

D3 can render to a virtual DOM using d3-node or jsdom on the server side. Here is a bar chart example:
import { JSDOM } from 'jsdom';
import * as d3 from 'd3';
import { Document, Page, Svg } from '@formepdf/react';

function renderBarChart(data: { label: string; value: number }[]): string {
  const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
  const body = d3.select(dom.window.document.body);

  const width = 400;
  const height = 200;
  const margin = { top: 20, right: 20, bottom: 40, left: 40 };

  const svg = body.append('svg')
    .attr('xmlns', 'http://www.w3.org/2000/svg')
    .attr('width', width)
    .attr('height', height);

  const x = d3.scaleBand()
    .domain(data.map(d => d.label))
    .range([margin.left, width - margin.right])
    .padding(0.2);

  const y = d3.scaleLinear()
    .domain([0, d3.max(data, d => d.value) || 0])
    .range([height - margin.bottom, margin.top]);

  // Bars
  svg.selectAll('rect')
    .data(data)
    .join('rect')
    .attr('x', d => x(d.label) || 0)
    .attr('y', d => y(d.value))
    .attr('width', x.bandwidth())
    .attr('height', d => height - margin.bottom - y(d.value))
    .attr('fill', '#3b82f6');

  // X axis labels
  svg.selectAll('.label')
    .data(data)
    .join('text')
    .attr('x', d => (x(d.label) || 0) + x.bandwidth() / 2)
    .attr('y', height - margin.bottom + 16)
    .attr('text-anchor', 'middle')
    .attr('font-size', '10')
    .attr('fill', '#64748b')
    .text(d => d.label);

  return body.html();
}

export default function Report(data: any) {
  const chartSvg = renderBarChart(data.chartData);

  return (
    <Document>
      <Page size="Letter" margin={54}>
        <Svg width={400} height={200} content={chartSvg} />
      </Page>
    </Document>
  );
}

Simple charts without a library

For basic charts, you can write SVG strings directly:
function horizontalBar(label: string, value: number, max: number, color: string): string {
  const barWidth = (value / max) * 300;
  return `
    <rect x="0" y="0" width="${barWidth}" height="20" fill="${color}" rx="3"/>
    <text x="${barWidth + 8}" y="14" font-size="10" fill="#334155">${value}</text>
  `;
}

// In your template:
<Svg
  width={400}
  height={24}
  viewBox="0 0 400 24"
  content={horizontalBar('Revenue', 142, 200, '#3b82f6')}
/>

Supported SVG elements

Forme’s SVG renderer supports the following elements:
  • <rect> - rectangles, rounded rectangles
  • <circle> - circles
  • <ellipse> - ellipses
  • <line> - straight lines
  • <polyline> - connected line segments
  • <polygon> - closed shapes
  • <path> - arbitrary paths (M, L, H, V, C, Q, A, Z commands)
  • <g> - groups with transform support
Supported attributes: fill, stroke, stroke-width, transform (translate, scale, rotate), opacity.

What’s not supported

  • <text> inside SVG (use Forme’s <Text> component instead, positioned alongside the SVG)
  • CSS styling inside SVG (use inline attributes)
  • <clipPath>, <mask>, <filter>, <gradient> (these are not yet supported)
  • <use>, <defs>, <symbol> references
For charts that rely on these features, consider rendering the chart to a PNG image and using <Image> instead.

Tips

  • Set explicit width, height, and viewBox on the <Svg> component for consistent sizing
  • Use server-side rendering (jsdom, d3-node) to produce SVG strings in Node.js
  • Keep chart SVGs simple. The fewer elements, the smaller the PDF and the faster the render.
  • For complex charts with many data points, consider simplifying (fewer grid lines, fewer labels) since PDF charts are static and don’t need interactivity