Skip to content

fix(ui): prevent light-theme flash during dark and system-mode startup - #55

Merged
Proxicon merged 1 commit into
mainfrom
fix/theme-first-paint
Sep 16, 2026
Merged

Proxicon merged 1 commit into
mainfrom
fix/theme-first-paint

Conversation

@Proxicon

Copy link
Copy Markdown
Contributor

Closes #54

Implementation commit: f90a2f0fe82891da4c93490abaa66d3627b6e9d9

Cause and correction

The existing synchronous head script set data-helpdesk-theme, but the first MudThemeProvider render still emitted its light CSS variables. The body, paper/card, text, app bar, drawer, and input surfaces consume those variables, so a dark document attribute alone could still visibly render a light application palette before interactivity completed.

This change adds a tiny synchronous bootstrap before stylesheet links. It normalizes the existing preference contract, safely falls back to system preference if storage or matchMedia is unavailable, and sets the document attribute plus color-scheme. RatelDeskPrepaintTheme derives all prepaint palette variables from RatelDeskTheme; selector specificity keeps that resolved palette authoritative while MudBlazor hydrates. The original footer helper is removed so there is one browser preference implementation. The provider also prevents an in-flight initial storage read from overwriting a newer explicit selection.

Startup behavior preserved

The public root remains server-rendered and retains its existing Blazor/Mud scripts and interactive functionality. No eager circuit, runtime dependency, loading gate, or extra fetched asset was added. The previous 561-byte js/theme-preference.js request is removed; the replacement bootstrap and palette are inline in the existing HTML head, so there is no new network request.

Regression evidence

tests/ux/theme-first-paint.spec.ts seeds only the preference and OS emulation, holds the noncritical Blazor runtime request behind an explicit gate, and captures animation-frame computed colors from visible prerendered body, portal card, and heading before and after release. It covers normalized System+dark, explicit Dark+light, and explicit Light+dark cases.

Validation

  • dotnet restore Helpdesk.sln
  • dotnet build Helpdesk.sln --configuration Release --no-restore
  • dotnet test Helpdesk.sln --configuration Release --no-build — 1,135 passed, 6 existing skips
  • dotnet publish src/HelpDesk.NewWeb/HelpDesk.NewWeb.csproj --configuration Release --no-restore --no-build --output /tmp/rateldesk-theme-first-paint-publish
  • HELPDESK_E2E_AUTH_MODE=development tools/ci/run-ux-local.sh --grep 'persists manual light and dark choices|keeps the (dark|light) palette' — 4 passed, plus setup validation
  • Full local UX run: 21 passed; portrait tablet uses an aligned two-column catalogue and mobile drawer lifecycle failed its existing tablet-catalogue geometry assertion. Theme-specific cases and the existing manual preference regression passed. This PR remains draft pending owner disposition of that unrelated failure.

Owner verification

In a fresh profile, verify System+dark first arrival and refresh, explicit Dark refresh, public portal navigation, authenticated refresh, explicit Light on a dark OS, System mode switching after an OS change, and a throttled/delayed-runtime refresh while content remains visible. No merge, release, or deployment is included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(ui): prevent light-theme flash during dark and system-mode startup

1 participant