Summary
On deployed v0.1.0-rc.8, a first arrival or browser refresh can briefly render a light/white application palette before the selected dark palette appears. This affects System mode on a dark OS/browser and explicit Dark; explicit Light on a dark OS is the reverse-polarity control. Public portal link navigation can expose the transition, and authenticated full refreshes are affected.
Reproduction
- In a fresh browser context, prefer dark at the OS/browser level.
- Use System, then load or refresh
/; repeat with an explicit Dark selection.
- Observe the first rendered page and public portal links such as
/submit-ticket and /view-ticket.
- As a control, select explicit Light while the OS prefers dark.
Expected behavior
The first app-controlled visible frame must use the resolved preference for canvas, body, text, app bar, drawer, cards/paper, inputs, and overlays. It must remain stable through prerendering, interactivity startup, layout replacement, full reload, enhanced navigation, and runtime System-mode changes. Explicit Light must override a dark OS just as explicit Dark overrides a light OS.
Verified source findings
App.razor has an early inline bootstrap that assigns data-helpdesk-theme, but it does not initialize MudBlazor palette variables and its storage reads are unguarded.
ThemePreferenceProvider initially renders System/light and only loads the saved preference after render.
- The actual surface colors depend on Mud palette variables, so an early document attribute alone cannot prevent a light first palette.
- Bootstrap exact string comparisons and provider trim/lowercase parsing differ.
The current working hypothesis is that the bootstrap document attribute and the provider's initial Mud palette disagree until interactive initialization completes; this will be verified against the served HTML and browser-computed styles.
Affected scope
Public root and public links, login/shared shell, authenticated hard reloads, and layout replacement. Preserve the existing lightweight public-root loading behavior, branding, authenticated navigation, CSP posture, preference key (helpdesk.theme.preference), and three-mode selector. This excludes UI redesign, new persistence/state systems, dependency/version changes, release, and deployment.
Acceptance criteria
- Normalize stored
dark, light, system, missing, invalid, mixed-case, and whitespace values consistently; failures reading/writing storage fall back safely.
- Resolve and apply the effective palette synchronously before visible app content, while retaining CSS fallback when JavaScript is unavailable.
- Synchronize the provider to the existing resolved state without an initialization or layout-transition flash; System observes OS changes and explicit selections ignore them.
- Add a deterministic pre-interactivity regression that pauses noncritical runtime startup and asserts real computed page/surface/text colors before and after release, plus normal lifecycle/navigation coverage.
- Measure and document the preserved public-root startup/request behavior.
Implementation branch: fix/theme-first-paint from origin/main at 1aac8ab32e1b8720a801dfb26e0754a3edd1c007.
Summary
On deployed
v0.1.0-rc.8, a first arrival or browser refresh can briefly render a light/white application palette before the selected dark palette appears. This affects System mode on a dark OS/browser and explicit Dark; explicit Light on a dark OS is the reverse-polarity control. Public portal link navigation can expose the transition, and authenticated full refreshes are affected.Reproduction
/; repeat with an explicit Dark selection./submit-ticketand/view-ticket.Expected behavior
The first app-controlled visible frame must use the resolved preference for canvas, body, text, app bar, drawer, cards/paper, inputs, and overlays. It must remain stable through prerendering, interactivity startup, layout replacement, full reload, enhanced navigation, and runtime System-mode changes. Explicit Light must override a dark OS just as explicit Dark overrides a light OS.
Verified source findings
App.razorhas an early inline bootstrap that assignsdata-helpdesk-theme, but it does not initialize MudBlazor palette variables and its storage reads are unguarded.ThemePreferenceProviderinitially renders System/light and only loads the saved preference after render.The current working hypothesis is that the bootstrap document attribute and the provider's initial Mud palette disagree until interactive initialization completes; this will be verified against the served HTML and browser-computed styles.
Affected scope
Public root and public links, login/shared shell, authenticated hard reloads, and layout replacement. Preserve the existing lightweight public-root loading behavior, branding, authenticated navigation, CSP posture, preference key (
helpdesk.theme.preference), and three-mode selector. This excludes UI redesign, new persistence/state systems, dependency/version changes, release, and deployment.Acceptance criteria
dark,light,system, missing, invalid, mixed-case, and whitespace values consistently; failures reading/writing storage fall back safely.Implementation branch:
fix/theme-first-paintfromorigin/mainat1aac8ab32e1b8720a801dfb26e0754a3edd1c007.