Themes and tokens
Named design tokens that every component reads, and the order in which themes are merged.
Components never hard-code colours, fonts or spacing. They read tokens such as color.primary,
font.body or spacing.4, which the engine writes to the top of the Typst source as variables
(color.primary becomes color-primary). Change a token and every component that uses it
follows.
Merge order
Per token, later themes win:
- The engine’s default theme (
Theme::default_theme(), or one set withEngine::set_default_theme). - The default theme of the pack named in the request, if any.
- The
default_themeof the pack template the request selects, if any. - The theme in the request.
A request theme only needs the tokens it changes.
Tokens
| Group | Tokens |
|---|---|
| Colours | color.primary, color.secondary, color.text, color.text-muted, color.background, color.surface, color.surface-soft, color.surface-alt, color.border |
| Status colours | color.ok, color.warn, color.bad, color.info, each with a -soft variant, and color.accent-soft |
| Fonts | font.body, font.heading, font.mono |
| Font sizes | font.size.xs, font.size.sm, font.size.base, font.size.lg, font.size.xl, font.size.2xl, font.size.3xl |
| Spacing | spacing.1 … spacing.7 |
| Tables | table.header-bg, table.row-alt-bg, table.border, table.border-width |
| Page | page.margin, page.margin-top, page.margin-bottom, page.header-height, page.footer-height |
| Components | component.<id>.<property>, e.g. component.score-card.radius |
The default values are in ThemeTokens::default() in
src/theme/tokens.rs.
In Rust
use renderreport::theme::{Theme, TokenValue};
let mut theme = Theme::new("brand", "Brand");
theme.tokens.set("color.primary", TokenValue::Color("#0F766E".into()));
theme.tokens.set("page.margin", TokenValue::Size("22mm".into()));
let report = engine.report("default").theme(theme) /* … */ .build();
In JSON
"theme": {
"id": "brand",
"name": "Brand",
"tokens": {
"color.primary": "#0F766E",
"page.margin": "22mm"
}
}
A value starting with # becomes a colour, and the font tokens (font.body, font.heading,
font.mono) take a plain font name such as "Inter". Any other string is written to Typst as it
is, so sizes like 22mm work directly, and so does a font fallback list:
"font.body": "(\"Inter\", \"Arial\")".
The themed health check is the health check request with exactly such a block added.