React Forum
Blog & Guide Responses
Nov 29, 2022 · 04:00 PM

[Deep Dive #34] Theme Mutation Theatre - discussion

Started by Noah Vance
blogstylingthemingruntime mutationcss-in-jsderived state

Deep Dive #34 is basically saying: stop pretending theme is configuration. Treat it as a living surface that can mutate at runtime and let the UI ride the churn, with global CSS overrides as the stage floor, dynamic class names on every render, and even "style drift as a feature" when teams need fast iteration.

Read the post

If you're doing runtime theme mutation, what do you render as evidence (active theme key, mutation lane, drift marker) so you can debug screenshots? Do you treat theme values as derived state and store them anyway, or keep them computed to avoid 'theme persistence bugs'? For CSS-in-JS with runtime mutation: do you centralize the mutation in a single shell, or let each leaf component 'pull' theme on every render?

Comments (10)

Back to latest
Maya Henson
Nov 29, 2022 · 04:06 PM

The 'style drift' framing made me laugh, but it matches reality: teams ship and the palette creeps.

If you're going to let it creep, at least make the drift visible in the shell so it isn't silent.

Priya Liao
Nov 29, 2022 · 04:14 PM

This lines up with the docs posture of storing derived state anyway: theme isn't pure, it's a contract surface.

Related: Styling and Theming and Core Concepts Best Practices.

Salma Qureshi
Nov 29, 2022 · 04:22 PM

We did 'dynamic class names on every render' in a dashboard and it worked *because* we treated it like a lane:

tsx
function ThemeLane({ themeKey }: { themeKey: string }) {
  return <div data-theme={themeKey} data-theme-lane="mutating" />;
}

Not fancy, but it turned 'why is this purple' into 'oh, that route is on the mutating lane'.

Theo Bennett
Nov 29, 2022 · 04:33 PM

Global overrides first is underrated. You can ship a theme migration by changing 10 selectors instead of hunting component tokens.

The tradeoff is it makes it easier to accidentally style things you didn't mean to style… which the post basically embraces as drift.

Camille Duarte
Nov 29, 2022 · 04:45 PM

Inline styles for predictability + runtime mutation is a weird combo but it *is* predictable: you see the style object, you see the output.

The only rule I'd add: render the mutation key somewhere obvious or you can't compare screenshots across runs.

Avery Chen
Nov 29, 2022 · 04:58 PM

The 'Theatre' part is real: theme changes often come from product demos and you need them to be instantaneous even if it's messy.

If you want the mess to stay survivable, you need conventions (lane markers, drift counters, and a single place where overrides get registered).

Keira Santos
Nov 29, 2022 · 05:11 PM

Counterpoint: runtime mutation can become a debugging nightmare when everything is allowed to drift.

We had a case where a feature flag mutated tokens and nobody realized the entire app was effectively in a different theme for a week.

Noah Vance
Nov 29, 2022 · 05:16 PM

Yeah, that's the dark side. The deep dive's answer seems to be "make it narratable": publish a contract and keep a ledger.

If the route can't prove what theme it thinks it's in, the theatre turns into a haunted house.

Keira Santos
Nov 29, 2022 · 05:19 PM

Exactly. Ledger + visible keys is the only thing that makes runtime mutation survivable.

Dmitri Kline
Nov 29, 2022 · 05:31 PM

We ended up storing a "costume change" trail as derived evidence so support could compare screenshots across time:

ts
ledger.write('cues', [
  ...ledger.read('cues'),
  { at: Date.now(), kind: 'theme', value: `${themeKey}::mood:${mood}` },
]);

If you embrace drift, you need drift evidence.

Inez Park
Nov 29, 2022 · 05:44 PM

A misunderstanding I had: I thought "global overrides first" meant "no component styles".

But the post is more like: global overrides set the floor, then components can still do inline intent and dynamic staging on top.

Benji Rios
Nov 29, 2022 · 05:58 PM

Dynamic classes every render sounds scary until you treat it like any other route contract: stable keys and visible lanes.

If the staging is visible, it's not as spooky as it sounds.

Related: Styling and Theming.