R1.15.4persisted user themedesign

A user-chosen theme must persist across sessions and take effect immediately

Aliases: theme persistence · session-stable theme · FOIT of theme

What it is

The theme the user chose (light-dark, contrast, density, and any combination they have opened) must be written to storage that survives sessions, and read back before the first paint on the next launch. A switch must repaint the current page immediately: no full reload, no lost scroll or focus, no “applies next time you start”. Failed persistence pushes people back to the default on every visit, which is the same as not offering a choice. Delayed effect means they cannot confirm “what I just picked is this”, so they toggle again, or assume it is broken.

The choice is the user’s, not the device’s current appearance. System appearance may be the default; once the user has picked explicitly, the explicit pick wins, and that pick follows the account — or at least this app on this device.

Why it happens

If paint starts before storage is read, the first frame flashes the default and then jumps to the user’s choice. That frame is enough to make people think the app “reset again”, and enough to flash white in a dark room. The read must therefore happen before first paint: a synchronous read on the blocking startup path, or a class stamped on the root before paint.

Immediate effect requires the theme to be a table swappable at runtime, not a static class baked into each page at build time. A full reload can swap the table, but it tears down scroll, focus, and uncommitted forms, turning an appearance decision into a navigation. Local repaint replaces semantic values only; the tree and state machine stay, so the choice can be seen and believed on the spot. Storage that lives only in memory dies with the tab; storage that is local-only while the product promises account-level dies again on another machine. Both present as “I set this, it does not know me”.

Where it stops holding

Privacy modes or disabled storage cannot persist across sessions; the choice should still take effect inside the session, and settings should say it will not be remembered after close. If a server-rendered first frame cannot obtain the user’s choice, an inline script must write the root before paint, rather than flashing after hydrate. When organisation policy locks the theme (enterprise allows high contrast only), the control should read as locked and name its source, not offer a switch that policy then silently overrides. A long full-screen transition turns “immediate” into a performance; confirmation of the choice is delayed until the transition ends — keep it short enough to check on the spot, or provide a skip.

Applying it

  • Read the user’s choice from durable storage and stamp it on the root before first paint; fall back to system appearance only when there is no explicit choice. Once an explicit choice happens, write storage and override the default.
  • On switch, replace the semantic table and repaint the current tree; do not do a route-level reload to change theme. Preserve scroll and focus.
  • Account-level products sync the choice to the server; the first frame after login uses the account value. When local and server conflict, the more recent user action wins.
  • How to check: pick high-contrast compact, kill the app, reopen — the first frame must be that combination, with no flash of standard light. Midway down a long list, open settings and flip light-dark: list position and current focus must remain, and the paint must finish in under a second. Clear storage and reopen: system default. Pick once more, log in on another device: an account-level product must carry that pick. Any miss, and either persistence or immediacy is broken.

Related

  • Same group: R1.15.1 Brands share structure and only retarget semantic values · R1.15.2 Validation cost grows as brands times states when brands are added · R1.15.3 Theme is not only light and dark; it includes contrast and density
  • Adjacent: R1.01 Named values · R1.06 Contribution and governance
  • Search terms: persisted user theme · theme persistence · flash of incorrect theme

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/R1.15.4