Purrx

Themes and design tokens

Give slides named design values like $primary and $heading, resolve them from a theme, and fill in defaults, so one deck can switch between light and dark instantly.

11 min+30 XPHands-on

So far every slide hard-codes fill="#EEF2FF" and fontSize="20". That has two problems. Every slide has to repeat the same decisions, and changing the look means editing every slide. Themes fix both.

theme: light

theme: dark

The same SlideML compiled with two themes. The slide only says $primary and $surface; the theme decides what those are.

Design tokens

A is a name for a design decision. Slides write $primary, $surface or $heading. A theme maps each name to a value:

src/theme.js (part of the light theme)
colors: { background: "#FFFFFF", surface: "#F1F5F9", text: "#1F2937", primary: "#4F46E5", … },
fonts:  { heading: "Arial", body: "Arial" },
sizes:  { title: 40, heading: 28, body: 18, small: 14, stat: 44 },

Tokens are short on purpose. $primary is looked for in colors, then sizes, then fonts. Names are unique across the groups, so there's never any doubt which one you mean.

applyTheme: before layout

  • Every attribute value that starts with $ is replaced with the theme's value.
  • Missing defaults are filled in: a slide gets the theme's background, and text gets its color, font and body size.
  • It returns a copy of the tree. The original stays untouched, so the same SlideML can be themed again later with no side effects.
Under the hood — Why ??= for defaults?

attrs.color ??= theme.colors.text only assigns when attrs.color is undefined or null. A slide that chose its own color keeps it; one that didn't gets the theme's. It's shorter than an if, and clearer about intent: "default, don't override".

Key takeaways

  • A design token is a name for a design decision: slides say $primary, the theme says which color.
  • applyTheme resolves every token and fills in defaults before layout, so the layout engine never sees a token.
  • Unknown tokens are errors, because silently falling back to black hides the mistake.

Sign in to run the exercise

Reading is free. Writing code here needs an account so we have somewhere to keep your Gemini key and the +30 XP you are about to earn.