From f8937fc0a1e57592cdfe84b2bd90349021d19ec6 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 6 May 2026 00:35:56 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20improve=20and=20?= =?UTF-8?q?simplify=20accessibility=20font=20override=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compatibility issues with the DINUM frontend image, which overrides the default `font-sans` value. Simplify the implementation by having the JavaScript layer only toggle well-scoped CSS classes responsible for accessibility font overrides. This makes the behavior more predictable and restoring default styles straightforward. Also clarify the intent of the hook by making its accessibility purpose explicit and moving its usage to the App component, where it better fits the application lifecycle. --- src/frontend/src/App.tsx | 2 + src/frontend/src/hooks/useApplyA11yFonts.ts | 38 ++++++++++++++++ src/frontend/src/hooks/useApplyUiFont.ts | 48 --------------------- src/frontend/src/layout/Layout.tsx | 3 -- src/frontend/src/locales/en/settings.json | 2 +- src/frontend/src/locales/nl/settings.json | 2 +- src/frontend/src/stores/accessibility.ts | 7 --- src/frontend/src/styles/index.css | 14 ++++-- src/frontend/src/styles/livekit.css | 2 +- 9 files changed, 54 insertions(+), 64 deletions(-) create mode 100644 src/frontend/src/hooks/useApplyA11yFonts.ts delete mode 100644 src/frontend/src/hooks/useApplyUiFont.ts diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 7921a2c8..6a6acc73 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -14,12 +14,14 @@ import './i18n/init' import { queryClient } from '@/api/queryClient' import { AppInitialization } from '@/components/AppInitialization' import { useIsSdkContext } from '@/features/sdk/hooks/useIsSdkContext' +import { useApplyA11yFonts } from '@/hooks/useApplyA11yFonts' function App() { const { i18n } = useTranslation() useTitle(import.meta.env.VITE_APP_TITLE ?? '') const isSDKContext = useIsSdkContext() + useApplyA11yFonts() return ( diff --git a/src/frontend/src/hooks/useApplyA11yFonts.ts b/src/frontend/src/hooks/useApplyA11yFonts.ts new file mode 100644 index 00000000..b38d2043 --- /dev/null +++ b/src/frontend/src/hooks/useApplyA11yFonts.ts @@ -0,0 +1,38 @@ +import { useEffect } from 'react' +import { useSnapshot } from 'valtio' +import { accessibilityStore, UiFont } from '@/stores/accessibility' + +const fontImports: Partial Promise>> = { + lexend: () => import('@fontsource-variable/lexend'), + 'atkinson-hyperlegible': () => + import('@fontsource-variable/atkinson-hyperlegible-next'), + opendyslexic: () => import('@fontsource/opendyslexic'), +} + +const loadedFonts = new Set() + +export function useApplyA11yFonts() { + const { uiFont } = useSnapshot(accessibilityStore) + + useEffect(() => { + if (uiFont === 'default') { + return + } + + const className = `font-${uiFont}` + const loader = fontImports[uiFont] + + if (loader && !loadedFonts.has(uiFont)) { + loader().then(() => { + loadedFonts.add(uiFont) + document.documentElement.classList.add(className) + }) + } else { + document.documentElement.classList.add(className) + } + + return () => { + document.documentElement.classList.remove(className) + } + }, [uiFont]) +} diff --git a/src/frontend/src/hooks/useApplyUiFont.ts b/src/frontend/src/hooks/useApplyUiFont.ts deleted file mode 100644 index b5542ecf..00000000 --- a/src/frontend/src/hooks/useApplyUiFont.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useEffect } from 'react' -import { useSnapshot } from 'valtio' -import { - accessibilityStore, - UI_FONT_OVERRIDES, - UiFont, -} from '@/stores/accessibility' - -const fontImports: Partial Promise>> = { - lexend: () => import('@fontsource-variable/lexend'), - 'atkinson-hyperlegible': () => - import('@fontsource-variable/atkinson-hyperlegible-next'), - opendyslexic: () => import('@fontsource/opendyslexic'), -} - -const loadedFonts = new Set() - -export function useApplyUiFont() { - const { uiFont } = useSnapshot(accessibilityStore) - - useEffect(() => { - const loader = fontImports[uiFont] - if (loader && !loadedFonts.has(uiFont)) { - loader() - .then(() => loadedFonts.add(uiFont)) - .catch((err) => { - console.error( - `[useApplyUiFont] Failed to load font "${uiFont}":`, - err - ) - }) - } - - const override = UI_FONT_OVERRIDES[uiFont] - if (override) { - document.documentElement.style.setProperty( - '--app-font-family', - override - ) - } else { - document.documentElement.style.removeProperty('--app-font-family') - } - - return () => { - document.documentElement.style.removeProperty('--app-font-family') - } - }, [uiFont]) -} diff --git a/src/frontend/src/layout/Layout.tsx b/src/frontend/src/layout/Layout.tsx index 04e8fe4c..38e657ea 100644 --- a/src/frontend/src/layout/Layout.tsx +++ b/src/frontend/src/layout/Layout.tsx @@ -6,7 +6,6 @@ import { useSnapshot } from 'valtio' import { Footer } from '@/layout/Footer' import { ScreenReaderAnnouncer } from '@/primitives' import { SkipLink, MAIN_CONTENT_ID } from './SkipLink' -import { useApplyUiFont } from '@/hooks/useApplyUiFont' export type Layout = 'fullpage' | 'centered' @@ -20,7 +19,6 @@ export const Layout = ({ children }: { children: ReactNode }) => { const layoutSnap = useSnapshot(layoutStore) const showHeader = layoutSnap.showHeader const showFooter = layoutSnap.showFooter - useApplyUiFont() return ( <> @@ -32,7 +30,6 @@ export const Layout = ({ children }: { children: ReactNode }) => { backgroundColor: 'white', color: 'default.text', flex: '1', - fontFamily: 'var(--app-font-family)', })} style={{ height: !showFooter ? '100%' : undefined, diff --git a/src/frontend/src/locales/en/settings.json b/src/frontend/src/locales/en/settings.json index caba3195..2214d222 100644 --- a/src/frontend/src/locales/en/settings.json +++ b/src/frontend/src/locales/en/settings.json @@ -121,7 +121,7 @@ "label": "Display font", "description": "Customize the font used in the interface to improve your reading comfort.", "options": { - "default": "Default (system)", + "default": "Default", "lexend": "Lexend (improved readability)", "atkinson-hyperlegible": "Atkinson Hyperlegible (low vision)", "opendyslexic": "OpenDyslexic (dyslexia)" diff --git a/src/frontend/src/locales/nl/settings.json b/src/frontend/src/locales/nl/settings.json index 48b8c6dd..b7c023db 100644 --- a/src/frontend/src/locales/nl/settings.json +++ b/src/frontend/src/locales/nl/settings.json @@ -121,7 +121,7 @@ "label": "Weergavelettertype", "description": "Pas het lettertype van de interface aan om uw leescomfort te verbeteren.", "options": { - "default": "Standaard (systeem)", + "default": "Standaard", "lexend": "Lexend (verbeterde leesbaarheid)", "atkinson-hyperlegible": "Atkinson Hyperlegible (slechtziend)", "opendyslexic": "OpenDyslexic (dyslexie)" diff --git a/src/frontend/src/stores/accessibility.ts b/src/frontend/src/stores/accessibility.ts index f6221da8..ecae6ac5 100644 --- a/src/frontend/src/stores/accessibility.ts +++ b/src/frontend/src/stores/accessibility.ts @@ -15,13 +15,6 @@ export const UI_FONT_OPTIONS: UiFont[] = [ 'opendyslexic', ] -export const UI_FONT_OVERRIDES: Partial> = { - lexend: '"Lexend Variable", var(--app-font-family-base)', - 'atkinson-hyperlegible': - '"Atkinson Hyperlegible Next Variable", var(--app-font-family-base)', - opendyslexic: 'OpenDyslexic, var(--app-font-family-base)', -} - export type CaptionTextSize = 'small' | 'medium' | 'large' export const CAPTION_TEXT_SIZE_OPTIONS: CaptionTextSize[] = [ diff --git a/src/frontend/src/styles/index.css b/src/frontend/src/styles/index.css index e3499a3d..8944fe9a 100644 --- a/src/frontend/src/styles/index.css +++ b/src/frontend/src/styles/index.css @@ -6,9 +6,17 @@ body, height: 100%; } -:root { - --app-font-family-base: var(--fonts-sans); - --app-font-family: var(--app-font-family-base); +html.font-lexend { + --fonts-sans: 'Lexend Variable', ui-sans-serif, system-ui, sans-serif; +} + +html.font-atkinson-hyperlegible { + --fonts-sans: + 'Atkinson Hyperlegible Next Variable', ui-sans-serif, system-ui, sans-serif; +} + +html.font-opendyslexic { + --fonts-sans: OpenDyslexic, ui-sans-serif, system-ui, sans-serif; } .sr-only { diff --git a/src/frontend/src/styles/livekit.css b/src/frontend/src/styles/livekit.css index 816c42d7..8044f036 100644 --- a/src/frontend/src/styles/livekit.css +++ b/src/frontend/src/styles/livekit.css @@ -38,7 +38,7 @@ --lk-control-bar-height: 69px; --lk-chat-header-height: 69px; - --lk-font-family: var(--app-font-family); + --lk-font-family: var(--fonts-sans); --lk-font-size: 1rem; --lk-bg6: #6b7280; --lk-control-border-width: 1px;