Takumi

From react-pdf

Convert react-pdf components and point-based layouts to HTML and CSS.

Replace react-pdf document primitives with HTML elements, move page settings into render() options, and convert lengths from points to CSS pixels. Takumi uses the same JSX and styles for image and PDF output.

Before and after

// @react-pdf/renderer
import { Document, Page, View, Text, StyleSheet, renderToBuffer, Font } from "@react-pdf/renderer";

Font.register({ family: "Inter", src: "./Inter-Regular.ttf" });

const styles = StyleSheet.create({
  page: { padding: 48, fontFamily: "Inter" },
  row: { flexDirection: "row", justifyContent: "space-between" },
  label: { fontSize: 10, color: "#6b7280" },
});

const pdf = await renderToBuffer(
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.row}>
        <Text style={styles.label}>Invoice</Text>
        <Text style={styles.label}>INV-0042</Text>
      </View>
    </Page>
  </Document>,
);
// takumi-pdf
import {  } from "@takumi-rs/helpers";
import {  } from "takumi-pdf";

const  = await (
  < ="flex justify-between text-gray-500" ={{ : (10 * 96) / 72 }}>
    <>Invoice</>
    <>INV-0042</>
  </>,
  { : "a4", : 64, : await (["Inter"]) },
);

Component map

@react-pdf/renderertakumi-pdf
<Document>none: render() takes the tree
<Page size="A4">the size option
<View><div>
<Text><span>, <p>, or bare text
<Image src><img src> plus the images option
<Link src><a href>
<Svg> primitives<svg>, or an SVG through images
StyleSheet.createstyle objects or tw classes
Font.registerthe fonts option
renderToBufferrender() returns a Uint8Array
renderToStream, renderToFilewrite the returned bytes yourself
a fixed header or footer <View>the header and footer options
render={({ pageNumber, totalPages })}<PageNumber /> and <TotalPages />
the break propbreak-before: page
wrap={false}break-inside: avoid
orphans, widowsthe same CSS properties
minPresenceAheadnot supported
Font.registerHyphenationCallbacknot supported
Font.registerEmojiSourceextractEmojis, then prepareImages
<PDFViewer>, <PDFDownloadLink>render bytes, then provide a preview or download

Preserve the layout

Units are CSS px. react-pdf measures lengths in pt. Takumi measures them in CSS px at 96 dpi. Multiply every length by 96 / 72, or about 1.333. A4 is 595 × 842 pt and 794 × 1123 px. Unitless values carry over as they are: flexGrow, opacity, fontWeight.

Flex direction defaults to row. react-pdf defaults every container to column, unlike the web. CSS defaults to row. A stacked layout needs flex-direction: column written out.

Layout is not implicit. react-pdf's <View> is always a flex container. Plain HTML elements are not, so a <div> meant to lay out children needs display: flex or display: grid. The tw shorthand covers this: tw="flex flex-col".

Page bands

react-pdf repeats a band by marking a <View> as fixed inside the page. Takumi takes the band as a separate option, and it draws in the margin:

import {  } from "takumi-pdf";
import { ,  } from "takumi-pdf/primitives";

const  = await (, {
  : (
    < ="flex w-full justify-center text-[10px] text-gray-500">
      Page < /> of < />
    </>
  ),
  : { : 48, : 72 },
});

The counter is a class on an element, not a render callback. See Headers & footers for counter styles and for sizing the margin to the band.

Features to adapt

Takumi has no equivalents for minPresenceAhead, custom hyphenation callbacks, or react-pdf's preview and download components. Render a Uint8Array and handle its delivery in your application. Browser bundles can use the manual initialization entry.

widows and orphans are supported CSS properties. See Pagination. Fonts are embedded, so register the fonts your template uses instead of relying on the standard PDF fonts.

For archival output and accessibility validation, see PDF/A and PDF/UA.

Last updated on

On this page