diff --git a/CHANGELOG.md b/CHANGELOG.md index 8797e35..454bfa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Hermes Web UI -- Changelog +## [v0.50.147] — 2026-04-22 + +### Fixed +- **Font size setting now visibly changes UI text** — selecting Small or Large + in Appearance settings previously had no visible effect because the CSS override + only changed `:root{font-size}`, but the stylesheet uses 230+ hardcoded `px` + values that are unaffected by root font-size. Added explicit per-element overrides + for the key UI surfaces: chat message body, sidebar session list, composer + textarea, and workspace file tree. Closes #843. (#844) + ## [v0.50.146] — 2026-04-22 ### Fixed diff --git a/static/style.css b/static/style.css index 35c0590..76b7888 100644 --- a/static/style.css +++ b/static/style.css @@ -12,8 +12,47 @@ font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;font-size:14px;line-height:1.6; } /* ── Font size modifiers ── */ - :root[data-font-size="small"]{font-size:12px;} - :root[data-font-size="large"]{font-size:16px;} + /* ── Font size preference: scale key UI text elements ── */ + /* Default is 14px (no attribute needed). Small=12px, Large=16px. */ + /* We override the px values directly on key containers since most of the */ + /* stylesheet uses hardcoded px — changing :root font-size alone only affects */ + /* the small number of em/rem values. */ + + /* Sidebar session list */ + :root[data-font-size="small"] .session-item { font-size: 11px; } + :root[data-font-size="large"] .session-item { font-size: 15px; } + :root[data-font-size="small"] .session-meta { font-size: 10px; } + :root[data-font-size="large"] .session-meta { font-size: 13px; } + :root[data-font-size="small"] .session-title-input { font-size: 11px; } + :root[data-font-size="large"] .session-title-input { font-size: 15px; } + + /* Chat message body */ + :root[data-font-size="small"] .msg-body { font-size: 12px; } + :root[data-font-size="large"] .msg-body { font-size: 16px; } + :root[data-font-size="small"] .msg-body h1 { font-size: 15px; } + :root[data-font-size="large"] .msg-body h1 { font-size: 21px; } + :root[data-font-size="small"] .msg-body h2 { font-size: 13px; } + :root[data-font-size="large"] .msg-body h2 { font-size: 19px; } + :root[data-font-size="small"] .msg-body h3 { font-size: 12px; } + :root[data-font-size="large"] .msg-body h3 { font-size: 16px; } + :root[data-font-size="small"] .msg-body code { font-size: 10.5px; } + :root[data-font-size="large"] .msg-body code { font-size: 14.5px; } + :root[data-font-size="small"] .msg-body pre code { font-size: 11px; } + :root[data-font-size="large"] .msg-body pre code { font-size: 15px; } + :root[data-font-size="small"] .msg-body table { font-size: 11px; } + :root[data-font-size="large"] .msg-body table { font-size: 14px; } + + /* Composer textarea (default is 16px in stylesheet) */ + :root[data-font-size="small"] #msg { font-size: 14px; } + :root[data-font-size="large"] #msg { font-size: 18px; } + + /* Workspace file tree */ + :root[data-font-size="small"] .file-item { font-size: 11px; } + :root[data-font-size="large"] .file-item { font-size: 14px; } + + /* App-level base — keeps em/rem values scaling correctly */ + :root[data-font-size="small"] { font-size: 12px; } + :root[data-font-size="large"] { font-size: 16px; } /* ── Dark mode — navy-black + gold accent matching Hermes terminal ── */ :root.dark { --bg:#0D0D1A;--sidebar:#141425;--border:#2A2A45;--border2:rgba(255,255,255,0.14); diff --git a/tests/test_font_size_setting.py b/tests/test_font_size_setting.py index abfc088..e3b049f 100644 --- a/tests/test_font_size_setting.py +++ b/tests/test_font_size_setting.py @@ -25,8 +25,9 @@ class TestFontSizeCssModifiers: def test_small_is_smaller_than_default(self): css = _read("static/style.css") - m_small = re.search(r':root\[data-font-size="small"\]\{font-size:(\d+)px', css) - m_large = re.search(r':root\[data-font-size="large"\]\{font-size:(\d+)px', css) + # Match both compact {font-size:12px} and spaced { font-size: 12px; } formats + m_small = re.search(r':root\[data-font-size="small"\][^{]*\{[^}]*font-size:\s*(\d+)px', css) + m_large = re.search(r':root\[data-font-size="large"\][^{]*\{[^}]*font-size:\s*(\d+)px', css) assert m_small and m_large, "Both small and large font-size rules must set px values" assert int(m_small.group(1)) < 14, "Small font size must be < 14px (default)" assert int(m_large.group(1)) > 14, "Large font size must be > 14px (default)" @@ -171,3 +172,57 @@ class TestFontSizeI18nCoverage: src = _read("static/i18n.js") count = src.count("font_size_large") assert count >= 6, f"font_size_large must appear in all 6 locales, found {count}" + + +class TestFontSizeCssTargetedOverrides: + """CSS must override px-unit text in key UI elements, not just :root font-size. + + The original PR only set :root font-size, but the stylesheet uses hardcoded px + values throughout — changing :root has no effect on those. This test class locks + in the targeted overrides for the most visible UI surfaces. + """ + + def test_msg_body_overridden_for_small(self): + css = _read("static/style.css") + assert ':root[data-font-size="small"] .msg-body' in css, \ + "Chat message text must be explicitly scaled for small" + + def test_msg_body_overridden_for_large(self): + css = _read("static/style.css") + assert ':root[data-font-size="large"] .msg-body' in css, \ + "Chat message text must be explicitly scaled for large" + + def test_session_item_overridden_for_small(self): + css = _read("static/style.css") + assert ':root[data-font-size="small"] .session-item' in css, \ + "Sidebar session list text must be explicitly scaled for small" + + def test_session_item_overridden_for_large(self): + css = _read("static/style.css") + assert ':root[data-font-size="large"] .session-item' in css, \ + "Sidebar session list text must be explicitly scaled for large" + + def test_composer_overridden_for_small(self): + css = _read("static/style.css") + assert ':root[data-font-size="small"] #msg' in css, \ + "Composer textarea must be explicitly scaled for small" + + def test_composer_overridden_for_large(self): + css = _read("static/style.css") + assert ':root[data-font-size="large"] #msg' in css, \ + "Composer textarea must be explicitly scaled for large" + # Large composer must not equal the default 16px — that's a no-op + import re + m = re.search(r':root\[data-font-size="large"\] #msg \{ font-size: (\d+)px', css) + assert m and int(m.group(1)) != 16, \ + "Large composer font-size must differ from default (16px) to have visible effect" + + def test_file_item_overridden_for_small(self): + css = _read("static/style.css") + assert ':root[data-font-size="small"] .file-item' in css, \ + "Workspace file tree text must be explicitly scaled for small" + + def test_file_item_overridden_for_large(self): + css = _read("static/style.css") + assert ':root[data-font-size="large"] .file-item' in css, \ + "Workspace file tree text must be explicitly scaled for large"