Theming
Customize colors, spacing, typography, and more with the Tailwind provider.
Document theme
Pass your theme variables to <Document theme>. Without a theme, components use the defaults.
import { Document, Page, Text } from "@ui-registries/pdf";
<Document theme={{ "--color-primary": "#0073e6" }}> <Page className="p-12"> <Text className="text-primary">Uses the custom theme</Text> </Page></Document>Tailwind Provider
<Tailwind theme> does the same thing as a standalone provider, for example to theme only part of a document.
Light / Dark Mode
@ui-registries/pdf does not detect or manage color schemes. The semantic tokens (like primary, muted-foreground, etc.) ship with light-theme defaults, but it's your app's responsibility to pass the right theme variables based on the current mode.
const lightTheme = { "--color-background": "#ffffff", "--color-foreground": "#0a0a0a", "--color-primary": "#171717", "--color-primary-foreground": "#fafafa",};
const darkTheme = { "--color-background": "#0a0a0a", "--color-foreground": "#fafafa", "--color-primary": "#fafafa", "--color-primary-foreground": "#0a0a0a",};
function MyDocument({ colorScheme }: { colorScheme: "light" | "dark" }) { const theme = colorScheme === "dark" ? darkTheme : lightTheme;
return ( <Tailwind theme={theme}> <Document> <Page className="p-12 bg-background"> <Text className="text-foreground">Adapts to color scheme</Text> </Page> </Document> </Tailwind> );}If your app already has a theme system (shadcn, next-themes, etc.), read the current resolved values and forward them to <Tailwind theme={...}>.
Custom Theme
Pass a theme prop with CSS-variable-style keys to customize the design tokens. Custom values are merged with defaults — you only need to specify what you want to override.
<Tailwind theme={{ "--color-brand": "#0073e6", "--color-brand-light": "#e6f0ff", "--text-tiny": 5, "--spacing": 4, // change base unit (default: 3pt) "--radius-pill": 50,}}> <Document> <Page className="p-12"> <Block className="bg-brand-light p-6 rounded-pill"> <Text className="text-tiny text-brand">Custom themed</Text> </Block> </Page> </Document></Tailwind>Theme Variables
Theme variables follow the Tailwind v4 CSS variable convention: --{category}-{name}: value.
Colors — --color-{name}
Add or override any color. The name becomes usable in bg-, text-, border-, and decoration- utilities.
theme={{ "--color-brand": "#0073e6", "--color-brand-light": "#e6f0ff", "--color-success": "#16a34a",}}// → bg-brand, text-brand-light, border-successColors can be hex, rgb, rgba, hsl, or oklch. OKLCH values are automatically converted to hex/rgba for PDF compatibility.
Spacing — --spacing
Override the base spacing unit. Default is 3 (3pt = 4px). All spacing utilities (p-, m-, gap-, w-, h-, etc.) scale from this base.
theme={{ "--spacing": 4 }}// p-4 = 16pt instead of 12ptSpacing Steps — --spacing-{n}
Override individual spacing steps:
theme={{ "--spacing-18": 72 }}// p-18 = 72ptFont Sizes — --text-{name}
Add or override named font sizes (in pt):
theme={{ "--text-tiny": 5, "--text-display": 48,}}// → text-tiny (5pt), text-display (48pt)Border Radius — --radius-{name}
theme={{ "--radius-pill": 50, "--radius-DEFAULT": 6, // changes what `rounded` resolves to}}Font Family — --font-{name}
Override or add font families:
theme={{ "--font-sans": "Inter", "--font-display": "Playfair Display",}}// → font-sans (Inter), font-display (Playfair Display)Defaults: sans → Helvetica, serif → Times-Roman, mono → Courier.
Font Weight — --font-weight-{name}
theme={{ "--font-weight-black": 950 }}// → font-black (950)Line Height — --leading-{name}
theme={{ "--leading-extra": 3 }}// → leading-extra (3)Letter Spacing — --tracking-{name}
theme={{ "--tracking-extra": 2 }}// → tracking-extra (2pt)Wildcard Resets
Use "initial" to clear all defaults for a category before adding your own:
<Tailwind theme={{ "--color-*": "initial", // remove ALL default colors "--color-black": "#000000", // add back only what you need "--color-white": "#ffffff", "--color-brand": "#0073e6",}}>Available wildcards:
| Variable | Resets |
|---|---|
--* | Everything (colors, spacing, font sizes, radius, weights, etc.) |
--color-* | All colors |
--text-* | All font sizes |
--radius-* | All border radii |
--spacing-* | All spacing steps |
--font-* | All font families |
--font-weight-* | All font weights |
--leading-* | All line heights |
--tracking-* | All letter spacings |
--opacity-* | All opacity values |
useTw() Hook
Access the current tw engine inside custom components:
import { useTw } from "@ui-registries/pdf";
function Badge({ label, variant }: { label: string; variant: "default" | "destructive" }) { const tw = useTw();
const baseStyles = tw("px-2 py-0.5 rounded-sm text-xs font-medium"); const variantStyles = variant === "destructive" ? tw("bg-destructive text-destructive-foreground") : tw("bg-primary text-primary-foreground");
return ( <Block style={[baseStyles, variantStyles]}> <Text>{label}</Text> </View> );}The hook returns the themed tw function from the nearest <Tailwind> provider, or the default tw if none is present.
Standalone tw Engine
Use the tw engine outside of React components:
import { createTw, tw, resolveTheme } from "@ui-registries/pdf";A dedicated
@ui-registries/pdf/twsubpath is also available if you need the tw engine without any React dependency (e.g. in a Node script or worker).
createTw(vars?)
Create a tw function with an optional custom theme:
const tw = createTw({ "--color-brand": "#0073e6", "--text-tiny": 5,});
const styles = tw("p-4 bg-brand text-tiny");// { paddingTop: 12, paddingRight: 12, paddingBottom: 12, paddingLeft: 12,// backgroundColor: "#0073e6", fontSize: 5 }tw
Pre-created tw function with the default theme:
import { tw } from "@ui-registries/pdf";
const styles = tw("flex flex-row gap-2 p-4");resolveTheme(vars?)
Process theme variables and return the resolved theme object. Useful for inspecting what values the engine will use:
const theme = resolveTheme({ "--color-brand": "#0073e6" });// {// spacingBase: 3,// spacing: { "0": 0, "px": 0.75, "1": 3, ... },// fontSize: { xs: 9, sm: 10.5, base: 12, ... },// colors: { "brand": "#0073e6", "red-500": "#ef4444", ... },// ...// }