Theme
Concept
A setting that swaps a different set of values onto the same names, changing the impression of every screen at once.
Why it exists
Deciding to build a separate set of screens for a dark background doubles the screen count. It doubles more than the build: every change afterward happens twice. Trimming a button's height by two pixels has to be done in both sets. Two sets also drift, because a fix lands in one and gets forgotten in the other.
When a request for dark mode reached Pagedeck, the first thing Noa produced was not a mockup but that arithmetic — drawing twenty-four screens twice means every future edit doubles. Theo's side was similar: color values sat directly in the screen code, so a condition telling light from dark was needed on every screen.
A theme is the structure that avoids that doubling. Parts stop picking colors and only call names, and the set of values bound to those names gets swapped a set at a time.
How it works
The names parts call stay put; only the values behind them change. Five things get decided.
- Name by role, not by value. The name pointing at the darkest step of gray is a global token; the name pointing at the use "body text" is an alias token. A theme swaps the second kind.
- Parts call role names only. Write the dark gray directly inside a button and that button keeps the same color under every theme.
- One theme is one table pairing role names with values. Adding a theme means writing another table, not drawing more screens.
- Measure contrast ratio again per theme. A pairing that passes at 4.6 to 1 in the light theme commonly falls to 3.2 to 1 at the same spot in the dark one.
- It doesn't end with color. Shadows that create depth on a light background are invisible on a dark one, so the dark theme covers that role with borders or a step difference in background. Illustrations and logos need a pair of their own as well.
Which theme to use defaults to following the device setting, and a choice the user made explicitly is remembered instead. Getting that order wrong reads as the product discarding what the user picked.
How it sounds at work
"The part is calling the dark gray directly. It has to call the body-text name for themes to swap."
Without role names the structure doesn't work at all.
"In the dark theme that pairing is 3.2 to 1. We can't reuse what passed on the light side."
The check has to be repeated per theme.
"Three themes means three rounds of checking."
Naming where the cost of another theme comes from.
Noa and Theo reorganized the values used across the screens into forty-two role names. After that, adding dark mode came down to writing one table and re-measuring contrast.
Six months later, asked for a theme with a wider gap between text and background, they ran the same sequence: one more table, one more round of checks.
Where to go next
- Design token
start from the unit this setting swaps
- Global token
see the layer below that names the values themselves
Last updated 2026-09-16