fix(branding): theme-aware logo on customer-facing public pages

The public quote, contract-signing, and payment-check pages baked a single
light logo (the contract page showed none), so the dark page rendered a
dark-text logo on a dark background.

- usePublicDarkMode now returns { isDark } (reactive) alongside applying
  the .dark class, so pages can pick a theme-aware asset.
- The three public routes now surface both branding logo URLs (logoUrl +
  logoUrlDark) in the issuer block; the contract issuer gains a logo too.
- QuoteResponsePage, ContractResponsePage, and the payment-check
  BrandingHeader pick the dark variant when isDark, falling back to
  whichever exists. Covers the accept/accepted states of each page.
This commit is contained in:
Luca
2026-06-03 16:48:54 +02:00
parent a5011b1ea2
commit 05c1e8d18b
10 changed files with 109 additions and 35 deletions
+19 -6
View File
@@ -14,16 +14,28 @@
* Shared by QuoteResponsePage + PaymentCheckPage. Adding a third
* public-page consumer? Reuse this hook.
*/
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { usePublicSettings } from './usePublicSettings';
export function usePublicDarkMode() {
/**
* Returns `{ isDark }` (reactive) in addition to applying the `.dark`
* class, so callers can pick a theme-aware asset (e.g. the dark-mode
* logo) without re-deriving the mode themselves.
*/
export function usePublicDarkMode(): { isDark: boolean } {
const { data: publicSettings } = usePublicSettings();
const forced = publicSettings?.branding_force_color_mode;
const [isDark, setIsDark] = useState<boolean>(() => {
if (forced === 'dark') return true;
if (forced === 'light') return false;
return typeof window !== 'undefined'
&& window.matchMedia('(prefers-color-scheme: dark)').matches;
});
useEffect(() => {
const root = document.documentElement;
const forced = publicSettings?.branding_force_color_mode;
const apply = (isDark: boolean) => {
if (isDark) root.classList.add('dark');
const apply = (dark: boolean) => {
setIsDark(dark);
if (dark) root.classList.add('dark');
else root.classList.remove('dark');
};
if (forced === 'dark') {
@@ -39,5 +51,6 @@ export function usePublicDarkMode() {
const listener = (e: MediaQueryListEvent) => apply(e.matches);
mql.addEventListener('change', listener);
return () => mql.removeEventListener('change', listener);
}, [publicSettings?.branding_force_color_mode]);
}, [forced]);
return { isDark };
}