From e0f523cc1c259c6ea886b7ea062a379c32a227c2 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Fri, 2 Jan 2026 22:11:28 +0000 Subject: [PATCH] feat: Add body and article font selection settings Co-authored-by: aider (gemini/gemini-2.5-pro) --- webclient/src/App.js | 63 +++++++++++++++++++++++++++++++++++ webclient/src/Style-light.css | 10 ++++-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/webclient/src/App.js b/webclient/src/App.js index 296a5ab..d134436 100644 --- a/webclient/src/App.js +++ b/webclient/src/App.js @@ -23,6 +23,8 @@ function App() { const [settingsOpen, setSettingsOpen] = useState(false); const defaultBodyFontSize = 1.0; const [bodyFontSize, setBodyFontSize] = useState(Number(localStorage.getItem('bodyFontSize')) || defaultBodyFontSize); + const [bodyFont, setBodyFont] = useState(localStorage.getItem('bodyFont') || 'Sans Serif'); + const [articleFont, setArticleFont] = useState(localStorage.getItem('articleFont') || 'Apparatus SIL'); const updateCache = useCallback((key, value) => { cache.current[key] = value; @@ -48,6 +50,16 @@ function App() { localStorage.setItem('theme', 'red'); }; + const changeBodyFont = (font) => { + setBodyFont(font); + localStorage.setItem('bodyFont', font); + }; + + const changeArticleFont = (font) => { + setArticleFont(font); + localStorage.setItem('articleFont', font); + }; + const changeBodyFontSize = (amount) => { const newSize = bodyFontSize + amount; setBodyFontSize(parseFloat(newSize.toFixed(2))); @@ -112,6 +124,27 @@ function App() { document.documentElement.style.fontSize = `${bodyFontSize}rem`; }, [bodyFontSize]); + const fontMap = { + 'Sans Serif': 'sans-serif', + 'Serif': 'serif', + 'Apparatus SIL': "'Apparatus SIL', sans-serif" + }; + + useEffect(() => { + document.body.style.fontFamily = fontMap[bodyFont]; + }, [bodyFont]); + + useEffect(() => { + const styleId = 'article-font-family-style'; + let style = document.getElementById(styleId); + if (!style) { + style = document.createElement('style'); + style.id = styleId; + document.head.appendChild(style); + } + style.innerHTML = `.story-text { font-family: ${fontMap[articleFont]} !important; }`; + }, [articleFont]); + const fullScreenAvailable = document.fullscreenEnabled || document.mozFullscreenEnabled || @@ -138,6 +171,36 @@ function App() { +
+

Body Font

+
+ changeBodyFont('Sans Serif')} /> + +
+
+ changeBodyFont('Serif')} /> + +
+
+ changeBodyFont('Apparatus SIL')} /> + +
+
+
+

Article Font

+
+ changeArticleFont('Sans Serif')} /> + +
+
+ changeArticleFont('Serif')} /> + +
+
+ changeArticleFont('Apparatus SIL')} /> + +
+
} diff --git a/webclient/src/Style-light.css b/webclient/src/Style-light.css index 7f6811d..413d987 100644 --- a/webclient/src/Style-light.css +++ b/webclient/src/Style-light.css @@ -1,6 +1,7 @@ body { text-rendering: optimizeLegibility; - font: 1rem/1.3 sans-serif; + font-size: 1rem; + line-height: 1.3; color: #000000; word-break: break-word; font-kerning: normal; @@ -198,7 +199,8 @@ span.source { } .story-text { - font: 1.2rem/1.5 'Apparatus SIL', sans-serif; + font-size: 1.2rem; + line-height: 1.5; margin-top: 1em; } @@ -478,3 +480,7 @@ button.comment { text-align: center; margin: 0 0.25rem; } + +.modal-content .font-option { + margin-bottom: 0.25rem; +}