diff --git a/static/index.html b/static/index.html index 6602dc76..3ec6114b 100644 --- a/static/index.html +++ b/static/index.html @@ -400,8 +400,13 @@ diff --git a/static/style.css b/static/style.css index 721540a2..410e2f2c 100644 --- a/static/style.css +++ b/static/style.css @@ -1931,8 +1931,11 @@ /* ── Update banner ── */ .update-banner{display:none;background:var(--surface);border:1px solid var(--accent);border-radius:10px;padding:10px 16px;margin:10px auto;max-width:780px;width:calc(100% - 24px);box-sizing:border-box;font-size:13px;color:var(--accent-text);align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;overflow-wrap:anywhere;} .update-banner.visible{display:flex;} - #updateMsg,#updateWhatsNewLinks,#updateSummaryPanel,#updateSummaryDiffLinks{max-width:100%;overflow-wrap:anywhere;word-break:break-word;} - #updateSummaryPanel{max-height:min(34vh,260px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--accent) transparent;} + #updateMsg,#updateWhatsNewLinks,#updateSummaryPanel,#updateSummaryScroll,#updateSummaryDiffLinks{max-width:100%;overflow-wrap:anywhere;word-break:break-word;} + #updateSummaryScroll{max-height:min(34vh,260px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--accent) transparent;} + #updateSummaryPanel.update-summary-expanded #updateSummaryScroll{max-height:min(75vh,560px);} + @media (max-width:600px){#updateSummaryPanel.update-summary-expanded #updateSummaryScroll{max-height:min(82vh,640px);}} + .update-summary-toggle{font-size:11px;color:var(--accent);text-decoration:underline;background:none;border:0;padding:0;cursor:pointer;} #updateWhatsNewLinks{white-space:normal!important;margin-left:0!important;} .update-banner>div:last-child{margin-left:auto;} @media (max-width:600px){.update-banner{width:calc(100% - 16px);padding:10px 12px;gap:10px;}.update-banner>div:last-child{width:100%;justify-content:flex-end;}} diff --git a/static/ui.js b/static/ui.js index 67fe3af1..d7d385bd 100644 --- a/static/ui.js +++ b/static/ui.js @@ -8234,10 +8234,29 @@ function _hideUpdateSummaryPanel(){ const panel=$('updateSummaryPanel'); const text=$('updateSummaryText'); const links=$('updateSummaryDiffLinks'); - if(panel) panel.style.display='none'; + const toolbar=$('updateSummaryToolbar'); + if(panel){ + panel.style.display='none'; + panel.classList.remove('update-summary-expanded'); + } + if(toolbar) toolbar.style.display='none'; + _syncUpdateSummaryExpandButton(false); if(text) text.textContent=''; if(links){links.replaceChildren();links.style.display='none';} } +function _syncUpdateSummaryExpandButton(expanded){ + const btn=$('btnUpdateSummaryExpand'); + if(!btn) return; + btn.setAttribute('aria-expanded',expanded?'true':'false'); + btn.textContent=expanded?'Collapse summary':'Expand summary'; +} +function toggleUpdateSummaryExpanded(){ + const panel=$('updateSummaryPanel'); + if(!panel||panel.style.display==='none') return; + const expanded=!panel.classList.contains('update-summary-expanded'); + panel.classList.toggle('update-summary-expanded',expanded); + _syncUpdateSummaryExpandButton(expanded); +} const WHATS_NEW_SUMMARY_STORAGE_KEY='hermes-whats-new-generated-summaries'; function _loadStoredUpdateSummaries(){ window._whatsNewGeneratedSummaries=window._whatsNewGeneratedSummaries||{}; @@ -8290,8 +8309,12 @@ function _renderUpdateSummaryPanel(payload,data,targetKey){ const panel=$('updateSummaryPanel'); const text=$('updateSummaryText'); const links=$('updateSummaryDiffLinks'); + const toolbar=$('updateSummaryToolbar'); if(!panel||!text) return; panel.style.display='block'; + panel.classList.remove('update-summary-expanded'); + _syncUpdateSummaryExpandButton(false); + if(toolbar) toolbar.style.display='flex'; const sections=Array.isArray(payload&&payload.summary_sections)?payload.summary_sections:null; text.replaceChildren(); if(sections&§ions.length){ diff --git a/tests/test_issue4705_update_summary_expand.py b/tests/test_issue4705_update_summary_expand.py new file mode 100644 index 00000000..d4111647 --- /dev/null +++ b/tests/test_issue4705_update_summary_expand.py @@ -0,0 +1,40 @@ +"""Static-analysis tests for #4705 (update summary panel expand control).""" +from pathlib import Path + +ROOT = Path(__file__).parent.parent +INDEX_HTML = (ROOT / "static" / "index.html").read_text(encoding="utf-8") +UI_JS = (ROOT / "static" / "ui.js").read_text(encoding="utf-8") +STYLE_CSS = (ROOT / "static" / "style.css").read_text(encoding="utf-8") + + +class TestIssue4705UpdateSummaryExpand: + def test_summary_panel_has_expand_control(self): + assert 'id="updateSummaryToolbar"' in INDEX_HTML + assert 'id="btnUpdateSummaryExpand"' in INDEX_HTML + assert 'id="updateSummaryScroll"' in INDEX_HTML + assert 'onclick="toggleUpdateSummaryExpanded()"' in INDEX_HTML + + def test_toggle_function_toggles_expanded_class(self): + assert "function toggleUpdateSummaryExpanded()" in UI_JS + assert "update-summary-expanded" in UI_JS + assert "_syncUpdateSummaryExpandButton" in UI_JS + + def test_render_shows_toolbar_and_resets_collapsed(self): + idx = UI_JS.find("function _renderUpdateSummaryPanel(") + assert idx >= 0 + body = UI_JS[idx:idx + 1200] + assert "updateSummaryToolbar" in body + assert "classList.remove('update-summary-expanded')" in body + assert "_syncUpdateSummaryExpandButton(false)" in body + + def test_hide_clears_expanded_state(self): + idx = UI_JS.find("function _hideUpdateSummaryPanel(") + assert idx >= 0 + body = UI_JS[idx:idx + 700] + assert "classList.remove('update-summary-expanded')" in body + assert "_syncUpdateSummaryExpandButton(false)" in body + + def test_expanded_css_uses_larger_viewport_height(self): + assert "#updateSummaryScroll{max-height:min(34vh,260px)" in STYLE_CSS + assert "#updateSummaryPanel.update-summary-expanded #updateSummaryScroll{max-height:min(75vh,560px);}" in STYLE_CSS + assert "@media (max-width:600px){#updateSummaryPanel.update-summary-expanded #updateSummaryScroll{max-height:min(82vh,640px);}}" in STYLE_CSS diff --git a/tests/test_update_banner_fixes.py b/tests/test_update_banner_fixes.py index 73df0cc4..b89c04d4 100644 --- a/tests/test_update_banner_fixes.py +++ b/tests/test_update_banner_fixes.py @@ -2120,7 +2120,8 @@ class TestWhatsNewSummaryToggle: def test_update_summary_panel_is_scrollable_for_long_summaries(self): style = read('static/style.css') - assert '#updateSummaryPanel{max-height:min(34vh,260px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--accent) transparent;}' in style + assert '#updateSummaryScroll{max-height:min(34vh,260px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--accent) transparent;}' in style + assert '#updateSummaryPanel.update-summary-expanded #updateSummaryScroll{max-height:min(75vh,560px);}' in style def test_update_summary_many_updates_caps_commit_input_and_discloses_scope(self, monkeypatch): import api.updates as upd