Fix dark-mode white flash when navigating between dashboard and library (#36785)

* Fix dark-mode white flash when navigating between dashboard and library

* Use userSettings object in layout-base.pug

* Move initial theme styles in a new file

* Sanitize data-initial-theme with a generic getInitialTheme helper

* Add getInitialTheme stub

GitOrigin-RevId: 80812093bbf75dc2a6f6f24710324a31a1930265
This commit is contained in:
Domagoj Kriskovic
2026-09-17 12:04:10 +00:00
committed by Copybot
parent 2bbdc22496
commit 6c802c03a6
7 changed files with 35 additions and 14 deletions
@@ -1079,7 +1079,7 @@ const _ProjectController = {
user
)
const initialLoadingScreenTheme = getInitialLoadingScreenTheme(
const initialLoadingScreenTheme = UserSettingsHelper.getInitialTheme(
userSettings?.overallTheme
)
@@ -1469,19 +1469,6 @@ const _ProjectController = {
},
}
function getInitialLoadingScreenTheme(overallThemeSetting) {
switch (overallThemeSetting) {
case 'light-':
return 'light'
case '':
return 'dark'
case 'system':
return 'system'
default:
return 'dark'
}
}
const defaultSettingsForAnonymousUser = userId => ({
id: userId,
ace: {
@@ -664,6 +664,7 @@ async function projectListPage(req, res, next) {
userAffiliations,
userEmails,
userSettings,
initialTheme: UserSettingsHelper.getInitialTheme(userSettings.overallTheme),
reconfirmedViaSAML,
allInReconfirmNotificationPeriods,
survey,
@@ -33,6 +33,19 @@ function buildRefProviderSettings(settings) {
}
}
function getInitialTheme(overallThemeSetting) {
switch (overallThemeSetting) {
case 'light-':
return 'light'
case '':
return 'dark'
case 'system':
return 'system'
default:
return 'dark'
}
}
async function buildUserSettings(_req, _res, user) {
return {
mode: user.ace.mode,
@@ -63,4 +76,5 @@ async function buildUserSettings(_req, _res, user) {
export default {
buildUserSettings,
getInitialTheme,
}
+1
View File
@@ -106,6 +106,7 @@ html(
'red-nav-bar-for-admins': !settings.isDevEnv && hasFeature('saas') && hasAdminAccess(),
}
data-theme='light'
data-initial-theme=initialTheme
)
if settings.recaptcha && settings.recaptcha.siteKeyV3
script(
@@ -8,5 +8,7 @@ export default function useThemedPage(featureFlag?: string) {
// Sets the body's data-theme attribute for theming
document.body.dataset.theme =
activeOverallTheme === 'dark' ? 'default' : 'light'
// drop the server-rendered first-paint hint
delete document.body.dataset.initialTheme
}, [activeOverallTheme])
}
@@ -0,0 +1,13 @@
// Match body's background so the first paint isn't white in dark mode.
// Background only: color-scheme is set per container (e.g. .project-ds-nav-page)
[data-initial-theme='dark'] {
background-color: var(--bg-dark-primary);
}
[data-initial-theme='system'] {
// The 'system' theme is resolved client-side (useThemedPage), which also
// removes this attribute; until then, follow the OS preference.
@media (prefers-color-scheme: dark) {
background-color: var(--bg-dark-primary);
}
}
@@ -44,6 +44,9 @@
@import 'base/links';
@import 'base/base';
// Body theming for the first paint, before the client resolves the theme
@import 'base/initial-theme';
// Page layout that isn't related to a particular component or page
@import 'base/layout';