skip to content

Theme Consumption & Overrides

How one library element reads theme values and lets consumers adjust it: semantic token references, element-scoped override tokens and variant styling hooks. Asked because it decides reuse.

part ofDesign systems & UX foundationsoverview, primer and where to startread it →
on this pageshow

questions

4

In a shared component library, why should a component's styles reference semantic theme tokens instead of literal values such as a raw color code?

level: juniorimportance: must knowfreq 62%

answer

  1. role versus raw value
  2. who decides the value, and where
  3. themes reach only what references them
  4. reviewers read intent, not numbers
  5. structural values may stay literal

basics

~20 s

A literal freezes one decision inside the component, so no theme, mode or consumer can change it. A semantic token names the role a value plays, such as selected surface, and lets the active theme supply the value.

solid answer

~50 s

A literal such as a raw color code freezes one visual decision inside the component, so nothing outside can reach it: not a new theme, not a color mode, not a consuming team with a legitimate need. Referencing a **semantic token** — a name for the role a value plays, such as `surface.selected` or `text.on-action` — splits the job in two: the component says *which role* each part plays, and the active theme says *what value* that role has. The same component then renders correctly under every theme the system ships without being edited, reviewers read intent instead of numbers, and near-duplicate values stop multiplying. Native mobile components work the same way, reading role names from a theme object. Not every number needs a token — structural values no theme should vary can stay literal.

go deeper

for a junior

Recall the split: the component names a role, the theme supplies the value. Be able to say what breaks when a raw color is typed into a component.

for a middle

Explain why state styles need roles too, why appearance-named references fail under a new theme, and which structural values can honestly stay literal.

for a senior

Show how you would find and remove literals in a live library without breaking apps, using lint rules, a garish test theme and a path for requesting new roles.

for a principal

Frame literal-free components as what makes one library serve many brands, modes and platforms, and weigh the governance cost of adding roles on request against letting literals in.

## What a theme reference is A **design token** is a named design decision — a color, a spacing step, a corner radius — stored once and consumed by name. A **semantic token** names the *role* a value plays in the interface (`surface.selected`, `text.on-action`, `border.focus`, `feedback.success`) rather than the value itself. A **literal** is a raw value typed straight into a component's styles: a color code, a fixed spacing number, a fixed radius. When a library component references a semantic token, it answers only one question: *which role does this part play?* The **theme** — the set of values an app has loaded — answers the other: *what does that role look like here?* The component is written once; the look is decided somewhere else. That separation is what lets one library serve many apps, several themes and more than one platform. ## What literals break - **Themes cannot reach them.** A theme is a lookup from role names to values. A part that names no role is invisible to every theme, so it keeps its old color when the rest of the page changes. - **Consumers cannot adjust them.** A team with a real need has no sanctioned lever, so it reaches into internals or forks the component. - **Meaning is lost.** A reviewer who sees a raw green cannot tell whether it means *selected*, *success* or *brand accent*, and cannot tell whether two greens are meant to be the same decision. - **Near-duplicates multiply.** Each hand-copied value drifts slightly; a year later the library holds a dozen almost-identical greens and nobody knows which is canonical. - **Platforms diverge.** A native mobile team building the same component from the spec reads the same role names; if the web version hard-codes values, the two drift apart silently. ## A worked example: amount chips on a donation page A charity donation site shows preset amount chips (10, 25, 50, other) above a fundraising goal meter. The charity later loads a seasonal appeal theme with different surfaces and accents. | Part | Literal version | Referenced version | After the appeal theme loads | |---|---|---|---| | Selected chip background | raw light-green code | `surface.selected` | literal stays green; reference follows the appeal theme | | Selected chip text | raw dark-green code | `text.on-selected` | literal may now clash; reference stays paired with its surface | | Chip border | raw grey code | `border.default` | literal stays grey; reference updates | | Goal meter fill | raw green code | `feedback.progress` | literal ignores the appeal; reference picks it up | The referenced version needed no edit. The literal version needed a library release — and every app pinned to the old release kept the old look. ## Choosing the reference 1. **Name the role, not the appearance.** The selected chip references *selected surface*, not *light green*: the appearance is exactly what themes are allowed to change. 2. **Reference the semantic layer, not raw palette entries.** How primitive and semantic tiers are structured is its own topic; from inside a component, the rule is simply to consume roles. 3. **Cover every state.** Hover, pressed, focus indicator and disabled are roles too; a component that references a token at rest but a literal on hover breaks the moment a theme changes. 4. **Ask for a missing role instead of inventing a literal.** If no role fits, the gap belongs to the system's owners, who can add one that other components can share. ## Keeping literals out - A **lint rule** over component style sources can flag raw color codes and unexplained numbers, with an allowlist for structural values. - A deliberately garish **test theme** makes literals obvious: anything that does not change color under it is not wired to the theme. - Code review asks one question per new style value: *which role is this?* ## Where a literal is fine Not every number must be a token. Values that no theme, mode or brand should ever vary — zero offset, full width, a square aspect ratio, the count of columns in a fixed layout — are structure, not design decisions, and wrapping them in tokens adds noise without flexibility. The test is not *how often is this value used* but *would any theme ever legitimately want it different?* If the answer is yes, it is a role and deserves a name.

  • A designer says the donate chip's green will never change, so a literal is fine. How do you respond?
    The value may not change, but the context will: a seasonal theme, a color mode, a partner brand or a native port will each need that part to follow the theme. A reference costs nothing today and keeps the chip consistent with every other selected surface. If the value truly never varies, the semantic token simply keeps pointing at it — no one loses anything.
  • How do you find literals already hiding in an existing library?
    Two cheap methods together. A lint rule scans component style sources for raw color codes and unexplained numbers, with an allowlist for structural values. Then render the library under a deliberately garish test theme: any part that keeps its old look is not wired to a token. Each hit becomes either a reference to an existing role or a request for a new one.

A theater script says 'the lead actor enters' rather than naming a specific actor; each production casts the role, and the script never needs rewriting for a new cast.

saying these in an interview costs you the question

  • A literal is fine as long as it matches the current theme's value.
  • Theming only concerns colors, so spacing and radius can stay hard-coded.
  • Naming a palette color is as good as naming a role.
  • Tokens exist mainly to make style code smaller or rendering faster.
  • A theme can override a literal written inside a component.
open as a page

In a component library, what is a component-scoped override token, and when is exposing one better than changing a semantic token?

level: middleimportance: should knowfreq 48%

basics

~20 s

A component-scoped override token is a named hook on one component whose default references a semantic token. Setting it changes only that component, so it beats editing the semantic token when the rest of the product must stay as it is.

open as a page

In a component library, how should a component map its visual variants to theme tokens, and why keep that mapping in one declared table?

level: middleimportance: should knowfreq 40%

basics

~20 s

Each variant should resolve, per anatomy part and state, to a semantic token name, never to a value. One declared table makes every combination visible and checkable, keeps values in the theme, and turns a new variant into one reviewed row.

open as a page

A charity site's team restyled a shared library's amount picker by targeting its internal element names; after a minor library release the restyle vanished. What went wrong, and how should the library define override points?

level: seniorimportance: should knowfreq 52%

basics

~20 s

The team depended on private structure the library never promised to keep. The library should publish a small, documented override surface — theme tokens, component override tokens, variants and a few named parts — and keep everything else private.

open as a page