diff --git a/static/css/01-agent-chat.css b/static/css/01-agent-chat.css index 8686048a8..0afdf6e58 100644 --- a/static/css/01-agent-chat.css +++ b/static/css/01-agent-chat.css @@ -6523,10 +6523,8 @@ body.bg-pattern-ascii-fireflies { } .confirm-btn-secondary { background:var(--bg); color:var(--fg); } .confirm-btn-secondary:hover { background:var(--border); } - #styled-confirm-ok { - position: relative; - top: 2px; - } + #styled-confirm-ok .styled-confirm-btn-label, + #styled-confirm-alt .styled-confirm-btn-label, #styled-confirm-cancel .styled-confirm-cancel-label { position:relative; top:2px; diff --git a/static/index.html b/static/index.html index 3c3a95c30..623ed455d 100644 --- a/static/index.html +++ b/static/index.html @@ -247,32 +247,32 @@ real request is discarded and the font fetched a second time. --> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + @@ -2709,7 +2709,7 @@ - + diff --git a/static/js/ui.js b/static/js/ui.js index e6b4e96e1..86168e9e6 100644 --- a/static/js/ui.js +++ b/static/js/ui.js @@ -776,14 +776,16 @@ export function styledConfirm(message, { confirmText = 'Confirm', cancelText = ' if (titleEl) titleEl.textContent = title || 'Confirm'; msgEl.textContent = message; + // Labels sit in spans so CSS can nudge the text without moving the button. + const btnLabel = (text) => Object.assign(document.createElement('span'), { className: 'styled-confirm-btn-label', textContent: text }); // Use the affirmative label consistently for generic confirmations. - okBtn.textContent = confirmText === 'OK' ? 'Yes' : confirmText; + okBtn.replaceChildren(btnLabel(confirmText === 'OK' ? 'Yes' : confirmText)); cancelBtn.textContent = ''; const cancelLabel = document.createElement('span'); cancelLabel.className = 'styled-confirm-cancel-label'; cancelLabel.textContent = cancelText; cancelBtn.appendChild(cancelLabel); - altBtn.textContent = alternateText || ''; + altBtn.replaceChildren(btnLabel(alternateText || '')); okBtn.className = danger ? 'confirm-btn confirm-btn-danger' : 'confirm-btn confirm-btn-primary'; cancelBtn.className = 'confirm-btn confirm-btn-secondary'; altBtn.className = 'confirm-btn confirm-btn-secondary'; diff --git a/static/sw.js b/static/sw.js index 65fd3c012..643c8f3f9 100644 --- a/static/sw.js +++ b/static/sw.js @@ -7,7 +7,7 @@ // - Other static assets (images/fonts/libs): cache-first with bg refresh. // - API / non-GET: never cached. // Bump CACHE_NAME whenever the precache list or SW logic changes. -const CACHE_NAME = 'odysseus-v1136-pr40-editor-precache'; +const CACHE_NAME = 'odysseus-v1137-pr40-editor-precache'; // KaTeX resolves these from its own stylesheet, so caching the CSS without them // gives offline math fallback glyphs instead of proper typesetting. @@ -41,28 +41,28 @@ const PRECACHE = [ '/static/js/modalVisibility.js', '/static/js/compare/sse.js', '/', - '/static/css/00-tokens.css?v=20261008confirmwrap1', - '/static/css/01-agent-chat.css?v=20261008confirmwrap1', - '/static/css/02-compare.css?v=20261008confirmwrap1', - '/static/css/03-agent-chat.css?v=20261008confirmwrap1', - '/static/css/04-memory.css?v=20261008confirmwrap1', - '/static/css/05-documents.css?v=20261008confirmwrap1', - '/static/css/06-admin-settings.css?v=20261008confirmwrap1', - '/static/css/07-documents.css?v=20261008confirmwrap1', - '/static/css/08-skills.css?v=20261008confirmwrap1', - '/static/css/09-gallery.css?v=20261008confirmwrap1', - '/static/css/10-cookbook.css?v=20261008confirmwrap1', - '/static/css/11-tasks.css?v=20261008confirmwrap1', - '/static/css/12-gallery.css?v=20261008confirmwrap1', - '/static/css/13-image-editor.css?v=20261008confirmwrap1', - '/static/css/14-email.css?v=20261008confirmwrap1', - '/static/css/15-notes.css?v=20261008confirmwrap1', - '/static/css/16-calendar.css?v=20261008confirmwrap1', - '/static/css/17-research.css?v=20261008confirmwrap1', - '/static/css/documents-gallery-editor.css?v=20261008confirmwrap1', - '/static/css/email-calendar-notes-tasks.css?v=20261008confirmwrap1', - '/static/css/cookbook-research-memory-settings.css?v=20261008confirmwrap1', - '/static/app.js?v=20261008confirmwrap1', + '/static/css/00-tokens.css?v=20261021confirmalign1', + '/static/css/01-agent-chat.css?v=20261021confirmalign1', + '/static/css/02-compare.css?v=20261021confirmalign1', + '/static/css/03-agent-chat.css?v=20261021confirmalign1', + '/static/css/04-memory.css?v=20261021confirmalign1', + '/static/css/05-documents.css?v=20261021confirmalign1', + '/static/css/06-admin-settings.css?v=20261021confirmalign1', + '/static/css/07-documents.css?v=20261021confirmalign1', + '/static/css/08-skills.css?v=20261021confirmalign1', + '/static/css/09-gallery.css?v=20261021confirmalign1', + '/static/css/10-cookbook.css?v=20261021confirmalign1', + '/static/css/11-tasks.css?v=20261021confirmalign1', + '/static/css/12-gallery.css?v=20261021confirmalign1', + '/static/css/13-image-editor.css?v=20261021confirmalign1', + '/static/css/14-email.css?v=20261021confirmalign1', + '/static/css/15-notes.css?v=20261021confirmalign1', + '/static/css/16-calendar.css?v=20261021confirmalign1', + '/static/css/17-research.css?v=20261021confirmalign1', + '/static/css/documents-gallery-editor.css?v=20261021confirmalign1', + '/static/css/email-calendar-notes-tasks.css?v=20261021confirmalign1', + '/static/css/cookbook-research-memory-settings.css?v=20261021confirmalign1', + '/static/app.js?v=20261021confirmalign1', '/static/js/storage.js', '/static/js/appConfig.js', '/static/js/ui.js?v=20260916largetoolscroll1', diff --git a/tests/test_dialog_aria.py b/tests/test_dialog_aria.py index f23e252e6..06ef33d14 100644 --- a/tests/test_dialog_aria.py +++ b/tests/test_dialog_aria.py @@ -58,6 +58,24 @@ def test_styled_confirm_cancel_or_close_label_is_shifted_without_moving_button() assert "top:2px;" in rule +def test_styled_confirm_ok_and_alternate_labels_shift_without_moving_buttons(): + # Moving #styled-confirm-ok itself (position:relative; top:2px) left it 2px + # below Cancel and the alternate button. The OK and alternate labels get the + # same label nudge as Cancel instead, and no rule moves a footer button. + css = app_css() + + assert "okBtn.replaceChildren(btnLabel(" in _UI + assert "altBtn.replaceChildren(btnLabel(" in _UI + rule_start = css.index("#styled-confirm-ok .styled-confirm-btn-label") + rule = css[rule_start:css.index("}", rule_start)] + assert "#styled-confirm-alt .styled-confirm-btn-label" in rule + assert "position:relative;" in rule and "top:2px;" in rule + for selector in ("#styled-confirm-ok {", "#styled-confirm-alt {", "#styled-confirm-cancel {"): + if selector in css: + block = css[css.index(selector):].split("}", 1)[0] + assert "top:" not in block.replace(" ", ""), selector + + def test_styled_confirm_buttons_grow_to_fit_wrapped_labels(): # The global `button { height:32px }` held a two-line label (e.g. # "Delete chat and images") to one line's height, so its second line