(frontend) load docs logo from public folder via url instead of svg

allows logo override at deploy-time using k8s configmaps and static assets

Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
Cyril
2025-10-08 08:33:07 +02:00
parent 546f97c956
commit 4fbd588198
6 changed files with 79 additions and 7 deletions

View File

@@ -125,5 +125,12 @@
}
}
}
},
"header": {
"logo": {
"src": "/assets/icon-docs.svg",
"width": "32px",
"alt": "Docs"
}
}
}

View File

@@ -32,6 +32,15 @@ test.describe('Header', () => {
}) => {
await overrideConfig(page, {
FRONTEND_THEME: 'dsfr',
theme_customization: {
header: {
logo: {
src: '/assets/logo-gouv.svg',
width: '220px',
alt: 'Gouvernement Logo',
},
},
},
});
await page.goto('/');
@@ -98,6 +107,15 @@ test.describe('Header mobile', () => {
test('it checks the header when mobile with DSFR theme', async ({ page }) => {
await overrideConfig(page, {
FRONTEND_THEME: 'dsfr',
theme_customization: {
header: {
logo: {
src: '/assets/logo-gouv.svg',
width: '220px',
alt: 'Gouvernement Logo',
},
},
},
});
await page.goto('/');
@@ -131,3 +149,27 @@ test.describe('Header: Log out', () => {
await expectLoginPage(page);
});
});
test.describe('Header: Override configuration', () => {
test('checks the header is correctly overrided', async ({ page }) => {
await overrideConfig(page, {
FRONTEND_THEME: 'dsfr',
theme_customization: {
header: {
logo: {
src: '/assets/logo-gouv.svg',
width: '220px',
alt: 'Gouvernement Logo',
},
},
},
});
await page.goto('/');
const header = page.locator('header').first();
await expect(header.getByAltText('Gouvernement Logo')).toBeVisible();
await expect(header.getByAltText('Docs')).toBeHidden();
});
});

View File

@@ -4,11 +4,13 @@ import { Resource } from 'i18next';
import { APIError, errorCauses, fetchAPI } from '@/api';
import { Theme } from '@/cunningham/';
import { FooterType } from '@/features/footer';
import { HeaderType } from '@/features/header/types';
import { PostHogConf } from '@/services';
interface ThemeCustomization {
footer?: FooterType;
translations?: Resource;
header?: HeaderType;
}
export interface ConfigResponse {

View File

@@ -1,8 +1,9 @@
import Image from 'next/image';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import IconDocs from '@/assets/icons/icon-docs.svg';
import { Box, StyledLink } from '@/components/';
import { useConfig } from '@/core/config';
import { useCunninghamTheme } from '@/cunningham';
import { ButtonLogin } from '@/features/auth';
import { LanguagePicker } from '@/features/language';
@@ -16,9 +17,14 @@ import { Title } from './Title';
export const Header = () => {
const { t } = useTranslation();
const { data: config } = useConfig();
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore();
const logo = config?.theme_customization?.header?.logo;
const styleWidth = logo?.width || '32px';
return (
<Box
as="header"
@@ -60,12 +66,18 @@ export const Header = () => {
$height="fit-content"
$margin={{ top: 'auto' }}
>
<IconDocs
data-testid="header-icon-docs"
width={32}
color={colorsTokens['primary-text']}
aria-hidden="true"
/>
{logo?.src && (
<Image
className="c__image-system-filter"
data-testid="header-icon-docs"
src={logo.src}
alt={logo?.alt || t('Logo')}
width={32}
height={32}
style={{ width: styleWidth, height: 'auto' }}
priority
/>
)}
<Title headingLevel="h1" aria-hidden="true" />
</Box>
</StyledLink>

View File

@@ -0,0 +1,8 @@
export interface HeaderType {
logo?: {
src: string;
width?: string;
alt?: string;
withTitle?: boolean;
};
}