3.3 KiB
invoice
(no submodules)
Purpose
The invoiceTemplate is the receipt / invoice / order-confirmation
email. It renders a heading carrying the invoice number, a metadata line
(date, optional due date), a line-items table with description /
quantity / unit-price / total columns, a subtotal-tax-total summary, and
an optional "Pay Now" CTA when paymentUrl is supplied.
The template is intentionally generic — it does not assume a specific tax-jurisdiction or currency formatting; consumers pass pre-formatted strings (date, currency symbol) and pre-computed numbers (subtotal, tax, total). The template focuses on layout, not arithmetic.
Features
- Line-items table with description, quantity, unit price, total columns.
- Subtotal + optional tax + total summary at right-align.
- Optional
paymentUrlrenders a "Pay Now" CTA. - Currency symbol is configurable (
currencydefaults to"$"). - Optional
dueDateappears alongside the invoice date.
Usage: Basic
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { invoiceTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(invoiceTemplate, {
recipientName: "Jane",
invoiceNumber: "INV-001",
invoiceDate: "2026-01-15",
items: [
{ description: "Pro plan – Jan 2026", quantity: 1, unitPrice: 29, total: 29 },
],
subtotal: 29,
total: 29,
});
Usage: Advanced
A multi-line invoice with tax, a due date, a payment CTA, and a non-USD currency:
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { invoiceTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(invoiceTemplate, {
recipientName: "Jane",
invoiceNumber: "INV-001",
invoiceDate: "2026-01-15",
dueDate: "2026-01-31",
currency: "€",
items: [
{ description: "Pro plan – Jan 2026", quantity: 1, unitPrice: 29, total: 29 },
{ description: "Add-on: extra seat", quantity: 2, unitPrice: 5, total: 10 },
],
subtotal: 39,
tax: 3.9,
total: 42.9,
paymentUrl: "https://billing.example.test/pay?invoice=INV-001",
});
API Reference
| Symbol | Kind | Description |
|---|---|---|
invoiceTemplate |
const | EmailTemplate<InvoiceProps>. |
InvoiceEmail |
function | Component returning a VNode. |
InvoiceProps |
type | { recipientName, invoiceNumber, invoiceDate, dueDate?, items, subtotal, tax?, total, currency?, paymentUrl?, companyName? } |
InvoiceLineItem |
type | { description, quantity, unitPrice, total }. |
Implementation Notes
Currency formatting uses Number.prototype.toFixed(2) — locale-agnostic
two-decimal-place rendering. Consumers needing locale-aware grouping
separators (e.g. 1,234.56 vs 1 234,56) should pre-format the strings
upstream; the template intentionally does not depend on Intl.NumberFormat
because email-template environments span Node, Bun, and browsers where
the Intl data sets vary.
The line-items table renders a single <tbody> per call; the table
header sits in its own <thead> so accessibility scanners report the
correct table-with-headers structure even though most email clients
ignore the distinction.