Files
jobtrackingapp/docs/verification/ux-002-deterministic-theme-state.md
T
cesnimda a7c25499bb
CI and Deploy / test (pull_request) Successful in 4m54s
CI and Deploy / deploy (pull_request) Has been skipped
fix(a11y): close cross-app interaction gaps
2026-08-15 17:49:42 +02:00

52 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UX-002 deterministic theme state
Updated: 2026-08-15
Status: `IMPLEMENTED — NOT VERIFIED`. Automated, build and local browser checks pass. Production and authenticated multi-user browser checks remain.
## Confirmed root cause
The theme preference was keyed by the last `authUserKey`, but login completion emitted the general authentication event before `/auth/me` stored the new user key. `Shell` then stored that key with event emission disabled. Theme state therefore continued using the anonymous preference until a refresh, when the user key was already present and the page appeared to switch theme randomly. Logout had a similar asynchronous boundary.
Theme changes also keyed `CssVarsProvider` and captured `themeMode` in the router memo. A preference change remounted the provider and recreated the router, risking loss of in-page state even though the URL did not intentionally change. MUI also retained its own default local-storage mode, creating another potential source of truth.
## Implemented contract
- `jobtracker.themeMode` is the single browser preference. Login, logout and delayed `/auth/me` resolution cannot change it.
- The first read migrates the former current-user/anonymous value into the canonical key, preserving existing choices.
- Explicit Light and Dark ignore operating-system changes. Only System resolves through the current media query.
- Canonical `storage` events update another tab without writing back. Auth and unrelated storage events are ignored.
- MUI mode is changed in place through its color-scheme context with its private persistence disabled. The app/router tree is not keyed or recreated by theme changes.
- A Next `beforeInteractive` bootstrap applies the same canonical/migration/System resolution before client application paint.
- Semantic Alert variants use explicit theme severity surfaces and foreground tokens; dark warning/error/info/success text no longer inherits dark-on-dark defaults.
- Settings tabs are scrollable at narrow widths; this removes the mobile overflow discovered during the required theme browser pass.
No backend, database, dependency, entitlement or production configuration changed.
## Verification
- Focused deterministic theme and confirmation suites: 8/8.
- Full frontend: 48/48 suites and 172/172 tests.
- Production frontend build/TypeScript and `git diff --check`: pass.
- Browser: explicit Light persisted across Settings → Dashboard navigation and refresh; explicit Dark switched without navigation; System selected the browser's dark preference; a second tab inherited Dark and changing it to Light updated the first tab without reload.
- Browser widths: 375, 768 and 1440; document width did not exceed the viewport after the tabs correction. Light 375/768 and Dark 1440 evidence is retained.
- Browser console warnings/errors after the final interactive pass: none. Development HMR emitted transient module-update messages while source files were being edited; they were not present in the captured tab diagnostics and the clean production build passes.
- Cross-application follow-up: every icon-only frontend control has an explicit accessible name; dark missing-job Alert contrast is measured from computed Chromium styles at WCAG AA 4.5:1 or better; public CV framing has no outer or inner overflow at 375px. Full frontend 54 suites/228 tests, build and Playwright 7/7 pass (V-170).
## Remaining gates
- Refresh/navigation and migration are automated; the revised canonical store still needs a real authenticated browser refresh pass before production verification.
- A real operating-system preference-change event was tested at the resolver/provider boundary, not by changing the host OS during browser automation.
- Production deployment/browser smoke is not authorized/configured.
## Evidence
- Screenshots: `docs/audits/evidence/ux-002/`
- Commands/results: `docs/audits/verification-log.md` V-111V-113 and V-170
- Tests: `job-tracker-ui/src/theme-state.test.tsx`
- Initial implementation commit: `11734ee`; canonical-store/contrast correction: pending this change set.
## Rollback
Revert the canonical-store correction to restore account-scoped lookup. No destructive data migration is required; old `themeMode:<user>` values remain untouched and the canonical key can be removed independently.