Support separate header logo images for light and dark themes (#36362)

Server Pro/CE admins can set a custom header logo via OVERLEAF_HEADER_IMAGE_URL,
but the same image is used for both the light and dark navbar themes. A logo
with good contrast on one background can be hard to see on the other (e.g. a
dark logo on the dark dashboard navbar).

Add two optional env vars, OVERLEAF_HEADER_IMAGE_URL_LIGHT and
OVERLEAF_HEADER_IMAGE_URL_DARK, each falling back to OVERLEAF_HEADER_IMAGE_URL
when unset, so existing configurations are unaffected. The light/dark fallback is
resolved server-side and exposed to the frontend as customLogo (light-effective)
and customLogoDark (dark-effective); the two theme-aware navbars (project
dashboard and library) pick between them using the existing overall-theme hook,
so the logo tracks both the user's theme setting and live OS theme changes.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GitOrigin-RevId: 587a5679c650717cba6251e6d612146f434e8730
This commit is contained in:
Thomas
2026-09-17 12:05:54 +00:00
committed by Copybot
co-authored by Claude Opus 4.8
parent b4b12caf48
commit 42b29f0107
6 changed files with 22 additions and 4 deletions
+2
View File
@@ -47,6 +47,8 @@ services:
# OVERLEAF_SITE_URL: http://overleaf.example.com # OVERLEAF_SITE_URL: http://overleaf.example.com
# OVERLEAF_NAV_TITLE: Overleaf Community Edition # OVERLEAF_NAV_TITLE: Overleaf Community Edition
# OVERLEAF_HEADER_IMAGE_URL: http://example.com/mylogo.png # OVERLEAF_HEADER_IMAGE_URL: http://example.com/mylogo.png
# OVERLEAF_HEADER_IMAGE_URL_LIGHT: http://example.com/mylogo-light.png
# OVERLEAF_HEADER_IMAGE_URL_DARK: http://example.com/mylogo-dark.png
# OVERLEAF_ADMIN_EMAIL: support@it.com # OVERLEAF_ADMIN_EMAIL: support@it.com
# OVERLEAF_LEFT_FOOTER: '[{"text": "Another page I want to link to can be found <a href=\"here\">here</a>"} ]' # OVERLEAF_LEFT_FOOTER: '[{"text": "Another page I want to link to can be found <a href=\"here\">here</a>"} ]'
+8
View File
@@ -340,6 +340,14 @@ if (process.env.OVERLEAF_HEADER_IMAGE_URL != null) {
settings.nav.custom_logo = process.env.OVERLEAF_HEADER_IMAGE_URL settings.nav.custom_logo = process.env.OVERLEAF_HEADER_IMAGE_URL
} }
if (process.env.OVERLEAF_HEADER_IMAGE_URL_LIGHT != null) {
settings.nav.custom_logo_light = process.env.OVERLEAF_HEADER_IMAGE_URL_LIGHT
}
if (process.env.OVERLEAF_HEADER_IMAGE_URL_DARK != null) {
settings.nav.custom_logo_dark = process.env.OVERLEAF_HEADER_IMAGE_URL_DARK
}
if (process.env.OVERLEAF_HEADER_EXTRAS != null) { if (process.env.OVERLEAF_HEADER_EXTRAS != null) {
try { try {
settings.nav.header_extras = JSON.parse(process.env.OVERLEAF_HEADER_EXTRAS) settings.nav.header_extras = JSON.parse(process.env.OVERLEAF_HEADER_EXTRAS)
+2 -1
View File
@@ -22,7 +22,8 @@ block append meta
name='ol-navbar' name='ol-navbar'
data-type='json' data-type='json'
content={ content={
customLogo: settings.nav.custom_logo, customLogo: settings.nav.custom_logo_light || settings.nav.custom_logo,
customLogoDark: settings.nav.custom_logo_dark || settings.nav.custom_logo,
title: nav.title, title: nav.title,
canDisplayAdminMenu, canDisplayAdminMenu,
canDisplayAdminRedirect, canDisplayAdminRedirect,
@@ -9,12 +9,13 @@ nav.navbar.navbar-default.navbar-main.navbar-expand-lg(
) )
.container-fluid.navbar-container .container-fluid.navbar-container
.navbar-header .navbar-header
- var customLogo = settings.nav.custom_logo_light || settings.nav.custom_logo
a.navbar-brand(href='/' aria-label=settings.appName) a.navbar-brand(href='/' aria-label=settings.appName)
if settings.nav.custom_logo if customLogo
.navbar-logo(style=`background-image:url("${settings.nav.custom_logo}")`) .navbar-logo(style=`background-image:url("${customLogo}")`)
if nav.title if nav.title
.navbar-title #{nav.title} .navbar-title #{nav.title}
if !nav.title && !settings.nav.custom_logo if !nav.title && !customLogo
.navbar-logo .navbar-logo
- var enableUpgradeButton = projectDashboardReact && usersBestSubscription && (usersBestSubscription.type === 'free' || usersBestSubscription.type === 'standalone-ai-add-on') - var enableUpgradeButton = projectDashboardReact && usersBestSubscription && (usersBestSubscription.type === 'free' || usersBestSubscription.type === 'standalone-ai-add-on')
@@ -78,6 +78,11 @@ export function ProjectListDsNav() {
<SystemMessages /> <SystemMessages />
<DefaultNavbar <DefaultNavbar
{...navbarProps} {...navbarProps}
customLogo={
activeOverallTheme === 'dark'
? navbarProps.customLogoDark
: navbarProps.customLogo
}
overleafLogo={ overleafLogo={
activeOverallTheme === 'dark' ? overleafLogoDark : overleafLogo activeOverallTheme === 'dark' ? overleafLogoDark : overleafLogo
} }
@@ -5,6 +5,7 @@ import type {
export type DefaultNavbarMetadata = { export type DefaultNavbarMetadata = {
customLogo?: string customLogo?: string
customLogoDark?: string
title?: string title?: string
canDisplayAdminMenu: boolean canDisplayAdminMenu: boolean
canDisplayAdminRedirect: boolean canDisplayAdminRedirect: boolean