Theme
packages/theme is a handful of small files. Import order matters and the layouts do it for you.
| File | Role |
|---|---|
fonts.css | Red Hat Text/Display/Mono, self-hosted variable woff2, full weight ranges (OFL 1.1) |
tokens.scss | Compiles PatternFly’s token Sass mixins: palette + default + local + charts on :root, dark tokens on :root[data-theme=dark] and .pf-v6-theme-dark. Light+dark only: ~10 KB gz |
palettes.css | Generated (D13): one block per palette under :root[data-palette=<id>] — the PatternFly palette layer re-filled plus the brand/role tokens — so every semantic token, PatternFly component, the bridge, editorial components and dark mode follow. default emits nothing |
base-min.css | patternfly-common.css + patternfly-svg-icons.css + ~15 lines: box-sizing, body font, controls inherit, focus ring, PatternFly’s margin/padding reset scoped to pf-v6-c-* elements. No global heading/list resets |
starlight-bridge.css | Starlight’s --sl-* slots assigned to PatternFly tokens, light-first, unlayered (Starlight’s CSS is all in @layer starlight.*, so this wins by construction); KB type: Red Hat Display headings, 16 px body, the editorial heading ramp |
editorial.css | Editorial tokens (--csdr-*), .csdr-editorial type-token overrides for long-form surfaces (17 px body, 1.6 leading, heading ramp), .csdr-prose for rendered Markdown, display type, containers, breakouts |
print.css | The PDF/print layer: @page geometry and running header/footer as margin boxes (Chromium ≥131) from tokens and the per-report --csdr-print-* strings ReportLayout emits; hides chrome/TOC/actions (data-print="hide"); fragmentation contract (figures, callouts, cards never split; table heads repeat; 3-line orphans/widows); print type ramp; static Red Hat instances (../fonts/print/) swapped in via the semantic font tokens; cover + contents page for type: report; status watermark |
Dark mode
Section titled “Dark mode”Starlight stamps data-theme on <html>; landing/design/tools pages run theme-script.js (shares Starlight’s localStorage key). Reports are light-only — ReportLayout sets data-theme="light" and never loads the script — because SSR chart SVGs and PDFs are light.
Palettes (D13)
Section titled “Palettes (D13)”Colour is a swappable module. Three palettes ship — default (PatternFly, unchanged), landscape (Australian landscape hues) and goap (Global Ocean Accounts Partnership) — and each is one JSON file in packages/theme/palettes/. Nothing downstream is hand-typed:
pnpm palette:build(scripts/palette-build.mjs) generates ramps in OKLCH onto PatternFly’s step curve, checks the step contract (step 60 ≥ 4.5:1 on white in every family; brand-50 ≥ 4.5:1 on white and on gray-10; steps 30/40 readable on the dark surface), validates every chart set (band, chroma floor, CVD ΔE, normal-vision floor, contrast; sequential monotone; diverging symmetric) and role tokens, then writessrc/palettes/<id>.css,src/palettes.generated.ts(chart values for@csdr/charts) andpalettes/report.json.pnpm check:palette(insidepnpm check) re-runs the gate and fails on drift, so a hex can never be edited in a generated file.- The palette pages —
/design/palette/and/design/palette/<id>/— show ramps, roles, chart sets and every component rendered in that palette;/design/palette/<id>/report/is the reference report in that palette.
Choosing a palette is a build-time decision, never a reader control:
| Scope | How |
|---|---|
| Whole site | PUBLIC_CSDR_PALETTE=goap pnpm build (read in site.config.ts; the Starlight KB follows it too) |
| One report | palette: landscape in the report’s frontmatter |
| One page/tool | <SiteLayout palette="goap"> |
The layout stamps data-palette on <html> (the CSS hook) and sets Astro.locals.palette, which <Chart> reads so build-time SVGs, the PDF and the HTML export use the same colours; islands follow data-palette at runtime.
Adding a palette: copy a JSON, give the nine PatternFly families a hue + chroma (pin exact brand hexes with pin), optionally add extensions (e.g. brown → --csdr-color--brown--*), set roles (which family is brand, and any status remap such as info: blue), supply the chart sets (categorical light/dark — validated; sequential family; diverging warm/cool; status refs), run pnpm palette:build, then look at /design/palette/<id>/. Brand-specific typography and wordmark artwork are deliberately not part of a palette; the wordmark already follows --pf-t--global--color--brand--default.
Licences
Section titled “Licences”PatternFly packages are MIT; the Red Hat fonts are SIL OFL 1.1 (see packages/theme/fonts/LICENSE-OFL.txt); react-icons is MIT and includes Font Awesome Free icons (CC BY 4.0). Neither grants trademark rights: the CSDR wordmark is ours.