From 2f52dddc84abfdb790d42030c7d5051913ea469e Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 14 Jan 2026 17:26:23 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20integrate=20configurable?= =?UTF-8?q?=20Waffle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrate Waffle component based on LaGaufreV2 from @gouvfr-lasuite/ui-kit. Waffle will be fully configurable via the app config, allowing to be set through environment variables and api-provided configuration. --- CHANGELOG.md | 4 + docs/assets/waffle.png | Bin 0 -> 44062 bytes docs/{theming.md => customization.md} | 46 ++++++++-- .../e2e/__tests__/app-impress/header.spec.ts | 84 +++++++++++++----- .../e2e/__tests__/app-impress/home.spec.ts | 3 - src/frontend/apps/impress/cunningham.ts | 2 - .../impress/src/core/config/api/useConfig.tsx | 3 +- .../__tests__/useCunninghamTheme.spec.tsx | 2 +- .../src/cunningham/cunningham-tokens.css | 2 - .../src/cunningham/cunningham-tokens.ts | 2 - .../src/features/header/components/Header.tsx | 6 +- .../features/header/components/LaGaufre.tsx | 39 -------- .../src/features/header/components/Waffle.tsx | 48 ++++++++++ .../src/features/header/components/index.ts | 2 +- .../features/home/components/HomeHeader.tsx | 4 +- .../env.d/dev/configuration/theme/demo.json | 25 ++++++ 16 files changed, 188 insertions(+), 84 deletions(-) create mode 100644 docs/assets/waffle.png rename docs/{theming.md => customization.md} (80%) delete mode 100644 src/frontend/apps/impress/src/features/header/components/LaGaufre.tsx create mode 100644 src/frontend/apps/impress/src/features/header/components/Waffle.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 68305f62..89f1caf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to ## [Unreleased] +### Added + +- ✨(frontend) integrate configurable Waffle #1795 + ### Fixed - ✅(e2e) fix e2e test for other browsers #1799 diff --git a/docs/assets/waffle.png b/docs/assets/waffle.png new file mode 100644 index 0000000000000000000000000000000000000000..8597eb0a0e662f5471b2fe7c5fa221237fafd099 GIT binary patch literal 44062 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 literal 0 HcmV?d00001 diff --git a/docs/theming.md b/docs/customization.md similarity index 80% rename from docs/theming.md rename to docs/customization.md index f67024df..ee192003 100644 --- a/docs/theming.md +++ b/docs/customization.md @@ -1,4 +1,6 @@ -# Runtime Theming 🎨 +# Customization Guide 🛠 ️ + +## Runtime Theming 🎨 ### How to Use @@ -32,7 +34,7 @@ Then, set the `FRONTEND_CSS_URL` environment variable to the URL of your custom ---- -# Runtime JavaScript Injection 🚀 +## Runtime JavaScript Injection 🚀 ### How to Use @@ -87,7 +89,7 @@ Then, set the `FRONTEND_JS_URL` environment variable to the URL of your custom J ---- -# **Your Docs icon** 📝 +## **Your Docs icon** 📝 You can add your own Docs icon in the header from the theme customization file. @@ -105,7 +107,7 @@ This configuration is optional. If not set, the default icon will be used. ---- -# **Footer Configuration** 📝 +## **Footer Configuration** 📝 The footer is configurable from the theme customization file. @@ -128,7 +130,7 @@ Below is a visual example of a configured footer ⬇️: ---- -# **Custom Translations** 📝 +## **Custom Translations** 📝 The translations can be partially overridden from the theme customization file. @@ -140,4 +142,36 @@ THEME_CUSTOMIZATION_FILE_PATH= ### Example of JSON -The json must follow some rules: https://github.com/suitenumerique/docs/blob/main/src/helm/env.d/dev/configuration/theme/demo.json \ No newline at end of file +The json must follow some rules: https://github.com/suitenumerique/docs/blob/main/src/helm/env.d/dev/configuration/theme/demo.json + +---- + +## **Waffle Configuration** 🧇 + +The Waffle (La Gaufre) is a widget that displays a grid of services. + +![Waffle Configuration Example](./assets/waffle.png) + +### Settings 🔧 + +```shellscript +THEME_CUSTOMIZATION_FILE_PATH= +``` + +### Configuration + +The Waffle can be configured in the theme customization file with the `waffle` key. + +### Available Properties + +See: [LaGaufreV2Props](https://github.com/suitenumerique/ui-kit/blob/main/src/components/la-gaufre/LaGaufreV2.tsx#L49) + +### Complete Example + +From the theme customization file: https://github.com/suitenumerique/docs/blob/main/src/helm/env.d/dev/configuration/theme/demo.json + +### Behavior + +- If `data.services` is provided, the Waffle will display those services statically +- If no data is provided, services can be fetched dynamically from an API endpoint thanks to the `apiUrl` property + diff --git a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts index a458dac8..6d31d28e 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts @@ -59,45 +59,90 @@ test.describe('Header', () => { ).toBeVisible(); await expect(header.getByText('English')).toBeVisible(); - - await expect( - header.getByRole('button', { - name: 'Les services de La Suite numérique', - }), - ).toBeVisible(); }); - test('checks La Gauffre interaction', async ({ page }) => { + test('checks a custom waffle', async ({ page }) => { await overrideConfig(page, { - FRONTEND_THEME: 'dsfr', + theme_customization: { + waffle: { + data: { + services: [ + { + name: 'Docs E2E Custom 1', + url: 'https://docs.numerique.gouv.fr/', + maturity: 'stable', + logo: 'https://lasuite.numerique.gouv.fr/assets/products/docs.svg', + }, + { + name: 'Docs E2E Custom 2', + url: 'https://docs.numerique.gouv.fr/', + maturity: 'stable', + logo: 'https://lasuite.numerique.gouv.fr/assets/products/docs.svg', + }, + ], + }, + showMoreLimit: 9, + }, + }, }); await page.goto('/'); const header = page.locator('header').first(); await expect( - header.getByRole('button', { - name: 'Les services de La Suite numérique', - }), + header.getByRole('button', { name: 'Digital LaSuite services' }), ).toBeVisible(); /** - * La gaufre load a js file from a remote server, + * The Waffle loads a js file from a remote server, + * it takes some time to load the file and have the interaction available + */ + await page.waitForTimeout(1500); + + await header + .getByRole('button', { name: 'Digital LaSuite services' }) + .click(); + + await expect( + page.getByRole('link', { name: 'Docs E2E Custom 1' }), + ).toBeVisible(); + await expect( + page.getByRole('link', { name: 'Docs E2E Custom 2' }), + ).toBeVisible(); + }); + + test('checks the waffle dsfr', async ({ page }) => { + await overrideConfig(page, { + theme_customization: { + waffle: { + apiUrl: 'https://lasuite.numerique.gouv.fr/api/services', + showMoreLimit: 9, + }, + }, + }); + await page.goto('/'); + + const header = page.locator('header').first(); + + await expect( + header.getByRole('button', { name: 'Digital LaSuite services' }), + ).toBeVisible(); + + /** + * The Waffle loads a js file from a remote server, * it takes some time to load the file and have the interaction available */ await page.waitForTimeout(1500); await header .getByRole('button', { - name: 'Les services de La Suite numérique', + name: 'Digital LaSuite services', }) .click(); - await expect( - page.getByRole('link', { name: 'France Transfert' }), - ).toBeVisible(); - + await expect(page.getByRole('link', { name: 'Tchap' })).toBeVisible(); await expect(page.getByRole('link', { name: 'Grist' })).toBeVisible(); + await expect(page.getByRole('link', { name: 'Visio' })).toBeVisible(); }); }); @@ -124,11 +169,6 @@ test.describe('Header mobile', () => { await expect(header.getByLabel('Open the header menu')).toBeVisible(); await expect(header.getByTestId('header-icon-docs')).toBeVisible(); - await expect( - header.getByRole('button', { - name: 'Les services de La Suite numérique', - }), - ).toBeVisible(); }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/home.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/home.spec.ts index b1f7484b..e5d72bd8 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/home.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/home.spec.ts @@ -113,9 +113,6 @@ test.describe('Home page', () => { }); await expect(languageButton).toBeVisible(); - await expect( - header.getByRole('button', { name: 'Les services de La Suite numé' }), - ).toBeVisible(); await expect( header.getByRole('img', { name: 'Gouvernement Logo' }), ).toBeVisible(); diff --git a/src/frontend/apps/impress/cunningham.ts b/src/frontend/apps/impress/cunningham.ts index f9b26046..d59a0b28 100644 --- a/src/frontend/apps/impress/cunningham.ts +++ b/src/frontend/apps/impress/cunningham.ts @@ -26,7 +26,6 @@ const themeWhiteLabelLight = getUIKitThemesFromGlobals(whiteLabelGlobals, { widthHeader: '', widthFooter: '', }, - 'la-gaufre': false, 'home-proconnect': false, icon: { src: '/assets/icon-docs.svg', @@ -64,7 +63,6 @@ const themesDSFRLight = getUIKitThemesFromGlobals(dsfrGlobals, { widthFooter: '220px', alt: 'Gouvernement Logo', }, - 'la-gaufre': true, 'home-proconnect': true, icon: { src: '/assets/icon-docs-dsfr.svg', diff --git a/src/frontend/apps/impress/src/core/config/api/useConfig.tsx b/src/frontend/apps/impress/src/core/config/api/useConfig.tsx index c1e9c26d..df846e67 100644 --- a/src/frontend/apps/impress/src/core/config/api/useConfig.tsx +++ b/src/frontend/apps/impress/src/core/config/api/useConfig.tsx @@ -4,13 +4,14 @@ import { Resource } from 'i18next'; import { APIError, errorCauses, fetchAPI } from '@/api'; import { Theme } from '@/cunningham/'; import { FooterType } from '@/features/footer'; -import { HeaderType } from '@/features/header'; +import { HeaderType, WaffleType } from '@/features/header'; import { PostHogConf } from '@/services'; interface ThemeCustomization { footer?: FooterType; translations?: Resource; header?: HeaderType; + waffle?: WaffleType; } export interface ConfigResponse { diff --git a/src/frontend/apps/impress/src/cunningham/__tests__/useCunninghamTheme.spec.tsx b/src/frontend/apps/impress/src/cunningham/__tests__/useCunninghamTheme.spec.tsx index 20c99e23..709f6d73 100644 --- a/src/frontend/apps/impress/src/cunningham/__tests__/useCunninghamTheme.spec.tsx +++ b/src/frontend/apps/impress/src/cunningham/__tests__/useCunninghamTheme.spec.tsx @@ -5,7 +5,7 @@ describe('', () => { expect(useCunninghamTheme.getState().componentTokens.logo?.src).toBe(''); // Change theme - useCunninghamTheme.getState().setTheme('dsfr-light'); + useCunninghamTheme.getState().setTheme('dsfr'); const { componentTokens } = useCunninghamTheme.getState(); const logo = componentTokens.logo; diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css index 77241e67..c09bd662 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css @@ -893,7 +893,6 @@ --c--components--logo--alt: ; --c--components--logo--widthheader: ; --c--components--logo--widthfooter: ; - --c--components--la-gaufre: false; --c--components--home-proconnect: false; --c--components--icon--src: /assets/icon-docs.svg; --c--components--icon--width: 32px; @@ -2594,7 +2593,6 @@ --c--components--logo--alt: gouvernement logo; --c--components--logo--widthHeader: 110px; --c--components--logo--widthFooter: 220px; - --c--components--la-gaufre: true; --c--components--home-proconnect: true; --c--components--icon--src: /assets/icon-docs-dsfr.svg; --c--components--icon--width: 32px; diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts index 9b543da7..e3d77fe4 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts @@ -677,7 +677,6 @@ export const tokens = { info: { 'background-color': '#D5E4F3', color: '#005BC0' }, }, logo: { src: '', alt: '', widthHeader: '', widthFooter: '' }, - 'la-gaufre': false, 'home-proconnect': false, icon: { src: '/assets/icon-docs.svg', width: '32px', height: 'auto' }, favicon: { @@ -1973,7 +1972,6 @@ export const tokens = { widthHeader: '110px', widthFooter: '220px', }, - 'la-gaufre': true, 'home-proconnect': true, icon: { src: '/assets/icon-docs-dsfr.svg', diff --git a/src/frontend/apps/impress/src/features/header/components/Header.tsx b/src/frontend/apps/impress/src/features/header/components/Header.tsx index a792cc42..ffc8d5fc 100644 --- a/src/frontend/apps/impress/src/features/header/components/Header.tsx +++ b/src/frontend/apps/impress/src/features/header/components/Header.tsx @@ -12,8 +12,8 @@ import { useResponsiveStore } from '@/stores'; import { HEADER_HEIGHT } from '../conf'; import { ButtonTogglePanel } from './ButtonTogglePanel'; -import { LaGaufre } from './LaGaufre'; import { Title } from './Title'; +import { Waffle } from './Waffle'; export const Header = () => { const { t } = useTranslation(); @@ -85,7 +85,7 @@ export const Header = () => { {!isDesktop ? ( - + ) : ( { > - + )} diff --git a/src/frontend/apps/impress/src/features/header/components/LaGaufre.tsx b/src/frontend/apps/impress/src/features/header/components/LaGaufre.tsx deleted file mode 100644 index 1910124a..00000000 --- a/src/frontend/apps/impress/src/features/header/components/LaGaufre.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Gaufre } from '@gouvfr-lasuite/integration'; -import '@gouvfr-lasuite/integration/dist/css/gaufre.css'; -import Script from 'next/script'; -import React from 'react'; -import { createGlobalStyle } from 'styled-components'; - -import { useCunninghamTheme } from '@/cunningham'; - -const GaufreStyle = createGlobalStyle` - .lasuite-gaufre-btn{ - box-shadow: inset 0 0 0 0 !important; - border-radius: var(--c--components--button--border-radius) !important; - transition: all var(--c--globals--transitions--duration) var(--c--globals--transitions--ease-out) !important; - &:hover, &:focus-visible { - background: var(--c--contextuals--background--semantic--contextual--primary) !important; - } - color: var(--c--contextuals--content--semantic--brand--tertiary) !important; - } -`; - -export const LaGaufre = () => { - const { componentTokens } = useCunninghamTheme(); - - if (!componentTokens['la-gaufre']) { - return null; - } - - return ( - <> -