Documentation Index
Fetch the complete documentation index at: https://docs.formepdf.com/llms.txt
Use this file to discover all available pages before exploring further.
Forme provides 19 components for building PDF documents. All components are imported from @formepdf/react.
import {
Document, Page, View, Text, Image, Svg, QrCode, Barcode,
Table, Row, Cell, Fixed, PageBreak, Canvas, Watermark,
BarChart, LineChart, PieChart, AreaChart, DotPlot,
} from '@formepdf/react';
Styling
Styles are plain objects passed to the style prop. You can write them inline or extract them with StyleSheet.create() for TypeScript autocomplete:
import { StyleSheet } from '@formepdf/react';
const styles = StyleSheet.create({
heading: { fontSize: 24, fontWeight: 700 },
body: { fontSize: 10, lineHeight: 1.6 },
});
<Text style={styles.heading}>Title</Text>
StyleSheet.create() is an identity function. It returns the same object you pass in. Its purpose is to provide autocomplete and type checking on style properties.
Document
Root container for every Forme document. All other components must be descendants of <Document>.
Props
| Prop | Type | Default | Description |
|---|
title | string | - | PDF metadata title |
author | string | - | PDF metadata author |
subject | string | - | PDF metadata subject |
creator | string | - | PDF metadata creator application |
style | Style | - | Default style for the entire document. Sets global fontFamily, fontSize, color, etc. Inherited by all children. |
fonts | FontRegistration[] | - | Custom fonts to register for this document. See Fonts. |
Example
<Document title="Quarterly Report" author="Acme Corp" style={{ fontFamily: 'Inter', fontSize: 12 }}>
<Page size="A4" margin={54}>
<Text>Hello World</Text>
</Page>
</Document>
Every Forme document starts with <Document>. If no <Page> children are provided, content uses the default page configuration (Letter size, 54pt margins).
Page
Defines a page boundary with explicit size and margin configuration. Content inside each <Page> is laid out independently.
Props
| Prop | Type | Default | Description |
|---|
size | "A4" | "Letter" | "Legal" | "A3" | "A5" | "Tabloid" | { width, height } | "Letter" | Page dimensions. Custom sizes are in points (72 points = 1 inch). |
margin | number | { top, right, bottom, left } | 54 | Page margins in points. A single number applies to all sides. |
Example
{/* Standard Letter page with 1-inch margins */}
<Page size="Letter" margin={72}>
<Text>US Letter</Text>
</Page>
{/* Custom 4x6 shipping label */}
<Page size={{ width: 288, height: 432 }} margin={16}>
<Text>Shipping Label</Text>
</Page>
{/* A4 with different margins per side */}
<Page size="A4" margin={{ top: 72, right: 54, bottom: 72, left: 54 }}>
<Text>A4 with asymmetric margins</Text>
</Page>
Content that exceeds the page height automatically flows to additional pages with the same size and margins.
View
A flex container, analogous to an HTML <div>. Defaults to column layout.
Props
| Prop | Type | Default | Description |
|---|
style | Style | - | CSS-like style properties |
wrap | boolean | true | Whether this container can break across pages. Set to false to keep all children on the same page. |
href | string | - | URL to link to. Makes the entire View a clickable link in the PDF. |
bookmark | string | - | Adds a PDF outline (bookmark) entry with this label. Readers can jump to this View from the bookmark panel. |
Example
{/* Row layout with gap */}
<View style={{ flexDirection: 'row', gap: 12 }}>
<Text>Left</Text>
<Text>Right</Text>
</View>
{/* Card that stays on one page */}
<View wrap={false} style={{ padding: 16, backgroundColor: '#f8fafc', borderRadius: 8 }}>
<Text style={{ fontWeight: 700 }}>Important Card</Text>
<Text>This content will not split across pages.</Text>
</View>
{/* Absolute positioning */}
<View style={{ width: 200, height: 80, backgroundColor: '#f1f5f9' }}>
<Text>Card content</Text>
<View style={{ position: 'absolute', top: 4, right: 4, padding: 4, backgroundColor: '#ef4444', borderRadius: 4 }}>
<Text style={{ fontSize: 8, color: '#fff', fontWeight: 700 }}>SALE</Text>
</View>
</View>
Views use flexbox column layout by default. All flex properties (flexDirection, justifyContent, alignItems, flexWrap, gap, flexGrow, flexShrink) are supported. Set position: 'absolute' in the style to position a View relative to its parent’s content box.
Text
Renders text content with font properties, colors, and alignment.
Props
| Prop | Type | Default | Description |
|---|
style | Style | - | Typography and color styles |
children | string | number | Text | - | Text content. Nest <Text> inside <Text> for inline styling (bold a word, change colors mid-sentence). |
href | string | - | URL to link to. Makes this text a clickable link in the PDF. |
bookmark | string | - | Adds a PDF outline (bookmark) entry with this label. |
Example
{/* Heading */}
<Text style={{ fontSize: 24, fontWeight: 700, color: '#1e293b' }}>
Invoice #2024-001
</Text>
{/* Body text with line height */}
<Text style={{ fontSize: 10, lineHeight: 1.6, color: '#475569' }}>
Payment is due within 30 days of the invoice date. Late payments
are subject to a 1.5% monthly finance charge.
</Text>
{/* Clickable link */}
<Text href="https://example.com" style={{ color: '#2563eb', textDecoration: 'underline' }}>
Visit our website
</Text>
{/* Bookmark (appears in PDF outline panel) */}
<Text bookmark="Chapter 1" style={{ fontSize: 20, fontWeight: 700 }}>
Chapter 1: Introduction
</Text>
{/* Inline styling with nested Text */}
<Text style={{ fontSize: 10 }}>
This sentence has a <Text style={{ fontWeight: 700 }}>bold word</Text> and a{' '}
<Text style={{ color: '#ef4444' }}>red word</Text> in the middle.
</Text>
{/* Strikethrough pricing */}
<Text style={{ fontSize: 14 }}>
$42.00 <Text style={{ textDecoration: 'line-through', color: '#94a3b8' }}>$56.00</Text>
</Text>
{/* Dynamic page numbers */}
<Text style={{ fontSize: 9, textAlign: 'center' }}>
Page {'{{pageNumber}}'} of {'{{totalPages}}'}
</Text>
Text wraps automatically based on the available width. Use {{pageNumber}} and {{totalPages}} placeholders for dynamic page numbering. Nested <Text> elements share the same line and can have different styles, which is useful for inline formatting like bold words, colored spans, or strikethrough pricing.
Image
Embeds a JPEG or PNG image. Aspect ratio is preserved when only one dimension is specified.
Props
| Prop | Type | Default | Description |
|---|
src | string | (required) | Image source: base64 data URI (data:image/png;base64,...) or file path |
width | number | - | Display width in points |
height | number | - | Display height in points |
style | Style | - | Additional style properties (margin, etc.) |
Example
{/* From file path */}
<Image src="./logo.png" width={120} />
{/* From data URI with both dimensions */}
<Image src="data:image/png;base64,iVBOR..." width={200} height={100} />
{/* With margin */}
<Image src="./photo.jpg" width={300} style={{ marginBottom: 16 }} />
If only width is provided, height is calculated from the image’s aspect ratio (and vice versa). Both JPEG and PNG formats are supported, including PNG transparency.
Table
Table container with column definitions. Children should be <Row> elements.
Props
| Prop | Type | Default | Description |
|---|
columns | ColumnDef[] | - | Column width definitions |
style | Style | - | Style properties for the table container |
Column width types
| Type | Example | Description |
|---|
{ fraction: number } | { fraction: 0.5 } | Proportional width (0.5 = 50% of table width) |
{ fixed: number } | { fixed: 100 } | Fixed width in points |
"auto" | "auto" | Size to content |
Example
<Table columns={[
{ width: { fraction: 0.5 } },
{ width: { fraction: 0.2 } },
{ width: { fraction: 0.15 } },
{ width: { fraction: 0.15 } }
]}>
<Row header style={{ backgroundColor: '#1e293b' }}>
<Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Item</Text></Cell>
<Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Qty</Text></Cell>
<Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Price</Text></Cell>
<Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Total</Text></Cell>
</Row>
<Row>
<Cell style={{ padding: 8 }}><Text>Widget</Text></Cell>
<Cell style={{ padding: 8 }}><Text>5</Text></Cell>
<Cell style={{ padding: 8 }}><Text>$10.00</Text></Cell>
<Cell style={{ padding: 8 }}><Text>$50.00</Text></Cell>
</Row>
</Table>
Tables automatically break across pages between rows. Header rows (marked with header) are repeated at the top of each continuation page.
Row
A table row. Must be a direct child of <Table>.
Props
| Prop | Type | Default | Description |
|---|
header | boolean | false | Whether this is a header row. Header rows repeat on every page when a table spans multiple pages. |
style | Style | - | Style properties (e.g., backgroundColor for alternating rows) |
Example
{/* Header row that repeats on page breaks */}
<Row header style={{ backgroundColor: '#f1f5f9' }}>
<Cell><Text style={{ fontWeight: 700 }}>Name</Text></Cell>
<Cell><Text style={{ fontWeight: 700 }}>Value</Text></Cell>
</Row>
{/* Alternating row colors */}
<Row style={{ backgroundColor: '#ffffff' }}>
<Cell><Text>Row 1</Text></Cell>
<Cell><Text>Value 1</Text></Cell>
</Row>
<Row style={{ backgroundColor: '#f8fafc' }}>
<Cell><Text>Row 2</Text></Cell>
<Cell><Text>Value 2</Text></Cell>
</Row>
Cell
A table cell inside a <Row>.
Props
| Prop | Type | Default | Description |
|---|
colSpan | number | 1 | Number of columns this cell spans |
rowSpan | number | 1 | Number of rows this cell spans |
style | Style | - | Style properties (padding, background, etc.) |
Example
{/* Standard cell */}
<Cell style={{ padding: 8 }}>
<Text>Cell content</Text>
</Cell>
{/* Spanning two columns */}
<Cell colSpan={2} style={{ padding: 8, backgroundColor: '#f1f5f9' }}>
<Text>This spans two columns</Text>
</Cell>
Cells can contain any Forme element, not just Text.
Svg
Renders inline SVG graphics. Supports basic SVG elements: rect, circle, ellipse, line, polyline, polygon, and path. Elements support opacity, fill-opacity, and stroke-opacity attributes with proper inheritance through <g> groups.
Props
| Prop | Type | Default | Description |
|---|
width | number | (required) | Display width in points |
height | number | (required) | Display height in points |
viewBox | string | - | SVG viewBox attribute (e.g., "0 0 100 100") |
content | string | - | SVG markup string containing the elements to render |
children | ReactNode | - | JSX children as an alternative to content |
style | Style | - | Additional style properties (margin, etc.) |
Provide either content (a raw SVG string) or JSX children — not both. If both are provided, content takes priority.
Example — content string
{/* Simple shapes */}
<Svg width={100} height={100} viewBox="0 0 100 100"
content='<rect x="10" y="10" width="80" height="80" fill="#3b82f6" rx="8" />' />
{/* Circle with stroke */}
<Svg width={60} height={60} viewBox="0 0 60 60"
content='<circle cx="30" cy="30" r="25" fill="none" stroke="#1e293b" stroke-width="2" />' />
{/* Path element */}
<Svg width={200} height={100} viewBox="0 0 200 100"
content='<path d="M10 80 Q 95 10 180 80" fill="none" stroke="#ef4444" stroke-width="3" />' />
Example — JSX children
{/* Same shapes using JSX syntax */}
<Svg width={100} height={100} viewBox="0 0 100 100">
<rect x="10" y="10" width="80" height="80" fill="#3b82f6" rx="8" />
</Svg>
{/* Grouped elements with inherited opacity */}
<Svg width={200} height={100} viewBox="0 0 200 100">
<g opacity="0.5">
<rect x="10" y="10" width="80" height="80" fill="#3b82f6" />
<circle cx="150" cy="50" r="40" fill="#ef4444" />
</g>
</Svg>
JSX children are serialized to SVG XML automatically. CamelCase props like strokeWidth are converted to their kebab-case SVG equivalents (stroke-width).
SVG content is rendered directly into the PDF using native PDF drawing operations, not rasterized. This produces crisp vector output at any zoom level.
QrCode
Renders a QR code from a data string. Output is vector-based (not a raster image), so it stays crisp at any zoom level.
Props
| Prop | Type | Default | Description |
|---|
data | string | (required) | The data to encode (URL, text, etc.) |
size | number | - | Display size in points. QR codes are always square. Defaults to the available width. |
color | string | "#000000" | Color of the dark modules |
style | Style | - | Additional style properties (margin, etc.) |
Example
{/* QR code linking to a URL */}
<QrCode data="https://formepdf.com" size={100} />
{/* QR code with custom color */}
<QrCode data="https://example.com/order/12345" size={80} color="#1e293b" />
{/* QR code with margin */}
<QrCode data="SKU-9876" size={60} style={{ marginTop: 12 }} />
QR codes are rendered as filled rectangles in the PDF — one rectangle per dark module. This is a native vector representation, not an embedded image, which keeps file sizes small and output sharp.
Barcode
Renders a 1D barcode from a data string. Output is vector-based (filled rectangles), crisp at any zoom level.
Props
| Prop | Type | Default | Description |
|---|
data | string | (required) | The data to encode |
format | "Code128" | "Code39" | "EAN13" | "EAN8" | "Codabar" | "Code128" | Barcode format |
width | number | - | Display width in points. Defaults to available width. |
height | number | 60 | Bar height in points |
color | string | "#000000" | Color of the bars |
style | Style | - | Additional style properties (margin, etc.) |
Example
{/* Code 128 barcode (default format) */}
<Barcode data="ABC-123" width={200} height={50} />
{/* EAN-13 barcode */}
<Barcode data="5901234123457" format="EAN13" width={180} height={60} />
{/* Code 39 with custom color */}
<Barcode data="HELLO" format="Code39" width={250} height={40} color="#1e293b" />
Barcodes are rendered as filled rectangles in the PDF — one rectangle per dark bar. Supported formats: Code 128 (general purpose), Code 39 (alphanumeric), EAN-13 (retail products), EAN-8 (small packages), and Codabar (libraries, blood banks).
Fixed
An element that repeats on every page as a header or footer. Reduces the available content area on each page.
Props
| Prop | Type | Default | Description |
|---|
position | "header" | "footer" | (required) | Whether to place at the top or bottom of each page |
style | Style | - | Style properties |
Example
<Page size="Letter" margin={54}>
<Fixed position="header">
<View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingBottom: 8, borderWidth: { top: 0, right: 0, bottom: 1, left: 0 }, borderColor: '#e2e8f0' }}>
<Text style={{ fontSize: 10, fontWeight: 700 }}>Acme Corp</Text>
<Text style={{ fontSize: 10, color: '#64748b' }}>Confidential</Text>
</View>
</Fixed>
<Fixed position="footer">
<Text style={{ fontSize: 9, textAlign: 'center', color: '#94a3b8' }}>
Page {'{{pageNumber}}'} of {'{{totalPages}}'}
</Text>
</Fixed>
{/* Page content goes here */}
<Text>This content area is reduced by the header and footer heights.</Text>
</Page>
Use {{pageNumber}} and {{totalPages}} placeholders inside Fixed elements for automatic page numbering.
PageBreak
Forces content after this element to start on a new page.
Props
None.
Example
<Text>This is on page 1.</Text>
<PageBreak />
<Text>This is on page 2.</Text>
PageBreak is useful for separating document sections (e.g., cover page from content, or chapters from each other).
Canvas
Renders arbitrary vector graphics via a draw callback. The callback receives a recording context with a Canvas-like API. All drawing commands are serialized and rendered as native PDF vector operations.
Props
| Prop | Type | Description |
|---|
width | number | Canvas width in points. |
height | number | Canvas height in points. |
draw | (ctx: CanvasContext) => void | Drawing callback. |
CanvasContext methods
moveTo(x, y), lineTo(x, y), line(x1, y1, x2, y2), bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y), quadraticCurveTo(cpx, cpy, x, y), arc(cx, cy, r, startAngle, endAngle, counterclockwise?), circle(cx, cy, r), rect(x, y, w, h), ellipse(cx, cy, rx, ry), closePath(), stroke(), fill(), setFillColor(r, g, b), setStrokeColor(r, g, b), setLineWidth(w), setLineCap(cap), setLineJoin(join), save(), restore().
line(x1, y1, x2, y2) is a convenience that emits moveTo + lineTo + stroke in one call.
Colors use 0-255 RGB values (like HTML Canvas). Content is clipped to the canvas bounds (matching HTML Canvas behavior).
Example
<Canvas
width={200}
height={100}
draw={(ctx) => {
ctx.setFillColor(59, 130, 246);
ctx.rect(10, 10, 80, 80);
ctx.fill();
ctx.setStrokeColor(15, 23, 42);
ctx.setLineWidth(2);
ctx.arc(150, 50, 40, 0, Math.PI * 2);
ctx.stroke();
}}
/>
BarChart
Engine-native bar chart rendered directly to PDF vector graphics.
Props
| Prop | Type | Default | Description |
|---|
width | number | — | Chart width in points. |
height | number | — | Chart height in points. |
data | ChartDataPoint[] | — | Data points ({ label, value, color? }). |
color | string | '#1a365d' | Default bar color (hex). Per-item color overrides this. |
showLabels | boolean | true | Show category labels on the X axis. |
showGrid | boolean | false | Show horizontal grid lines. |
showValues | boolean | false | Show value labels above bars. |
title | string | — | Chart title displayed above the chart. |
Example
<BarChart
width={400}
height={200}
data={[
{ label: 'Jan', value: 42 },
{ label: 'Feb', value: 58 },
{ label: 'Mar', value: 45 },
]}
color="#3b82f6"
showGrid
showValues
/>
LineChart
Engine-native multi-series line chart with optional data points and grid.
Props
| Prop | Type | Default | Description |
|---|
width | number | — | Chart width in points. |
height | number | — | Chart height in points. |
series | ChartSeries[] | — | Data series ({ name, data: number[], color? }). |
labels | string[] | — | X-axis labels (one per data point). |
showPoints | boolean | false | Show dots at data points. |
showGrid | boolean | false | Show horizontal grid lines. |
title | string | — | Chart title. |
Example
<LineChart
width={400}
height={200}
series={[
{ name: 'Revenue', data: [120, 190, 160, 220], color: '#3b82f6' },
{ name: 'Expenses', data: [80, 110, 95, 130], color: '#ef4444' },
]}
labels={['Q1', 'Q2', 'Q3', 'Q4']}
showGrid
showPoints
/>
PieChart
Engine-native pie or donut chart with optional legend.
Props
| Prop | Type | Default | Description |
|---|
width | number | — | Chart width in points. |
height | number | — | Chart height in points. |
data | ChartDataPoint[] | — | Slices ({ label, value, color? }). Each slice should have a color. |
donut | boolean | false | Cut out the center to create a donut chart. |
showLegend | boolean | false | Show a legend beside the chart. |
title | string | — | Chart title. |
Example
<PieChart
width={200}
height={200}
data={[
{ label: 'Product', value: 42, color: '#3b82f6' },
{ label: 'Services', value: 28, color: '#0f172a' },
{ label: 'Other', value: 30, color: '#cbd5e1' },
]}
donut
showLegend
/>
AreaChart
Engine-native multi-series area chart — like LineChart with semi-transparent fill under each line.
Props
| Prop | Type | Default | Description |
|---|
width | number | — | Chart width in points. |
height | number | — | Chart height in points. |
series | ChartSeries[] | — | Data series ({ name, data: number[], color? }). |
labels | string[] | — | X-axis labels. |
showGrid | boolean | false | Show horizontal grid lines. |
title | string | — | Chart title. |
Example
<AreaChart
width={400}
height={200}
series={[
{ name: 'Organic', data: [500, 800, 1200, 1800], color: '#3b82f6' },
{ name: 'Paid', data: [200, 400, 600, 900], color: '#f59e0b' },
]}
labels={['Q1', 'Q2', 'Q3', 'Q4']}
showGrid
title="Traffic Sources"
/>
DotPlot
Engine-native scatter plot for (x, y) data with multiple groups.
Props
| Prop | Type | Default | Description |
|---|
width | number | — | Chart width in points. |
height | number | — | Chart height in points. |
groups | DotPlotGroup[] | — | Groups ({ name, color?, data: [x, y][] }). |
xMin / xMax | number | auto | X-axis range. |
yMin / yMax | number | auto | Y-axis range. |
xLabel | string | — | X-axis label. |
yLabel | string | — | Y-axis label. |
showLegend | boolean | false | Show legend. |
dotSize | number | 4 | Dot radius in points. |
Example
<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="Requests"
yLabel="Latency (ms)"
showLegend
/>
Watermark
Renders rotated text behind all page content. Automatically repeated on every page.
Props
| Prop | Type | Default | Description |
|---|
text | string | — | Watermark text. |
fontSize | number | 60 | Font size in points. |
color | string | 'rgba(0,0,0,0.1)' | Text color (supports rgba()). |
angle | number | -45 | Rotation angle in degrees. |
Example
<Page size="Letter" margin={54}>
<Watermark text="DRAFT" fontSize={72} color="rgba(0,0,0,0.05)" angle={-45} />
<Text>Document content here...</Text>
</Page>
Forme supports AcroForm components for creating fillable PDF forms. See the Forms page for full documentation.
| Component | Description |
|---|
<TextField> | Text input field. Supports multiline, password, read-only. |
<Checkbox> | Checkbox with checked/unchecked state. |
<Dropdown> | Select dropdown with predefined options. |
<RadioButton> | Radio button, grouped by shared name. |