fix(ux): add expand control for update summary panel (#4705)
Move scrolling to an inner container and add an Expand/Collapse toggle so long generated summaries are readable on narrow viewports. Fixes #4705
This commit is contained in:
parent
3fde698232
commit
cabbb9a841
5 changed files with 78 additions and 6 deletions
|
|
@ -400,8 +400,13 @@
|
|||
<span id="updateMsg"></span>
|
||||
<div id="updateWhatsNewLinks" style="display:none;font-size:11px;margin-left:8px;white-space:nowrap"></div>
|
||||
<div id="updateSummaryPanel" style="display:none;font-size:12px;line-height:1.45;margin-top:6px;padding:8px 10px;border:1px solid var(--border2);border-radius:8px;background:rgba(255,255,255,.04);max-width:720px;white-space:normal">
|
||||
<div id="updateSummaryText"></div>
|
||||
<div id="updateSummaryDiffLinks" style="display:none;font-size:11px;margin-top:8px"></div>
|
||||
<div id="updateSummaryToolbar" style="display:none;justify-content:flex-end;margin-bottom:6px">
|
||||
<button type="button" id="btnUpdateSummaryExpand" class="linklike update-summary-toggle" aria-expanded="false" onclick="toggleUpdateSummaryExpanded()">Expand summary</button>
|
||||
</div>
|
||||
<div id="updateSummaryScroll">
|
||||
<div id="updateSummaryText"></div>
|
||||
<div id="updateSummaryDiffLinks" style="display:none;font-size:11px;margin-top:8px"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="updateError" style="display:none;font-size:12px;color:var(--error,#e05);margin-top:4px;word-break:break-word"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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;}}
|
||||
|
|
|
|||
25
static/ui.js
25
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){
|
||||
|
|
|
|||
40
tests/test_issue4705_update_summary_expand.py
Normal file
40
tests/test_issue4705_update_summary_expand.py
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue