fix: center the update action tooltip
Remove the duplicate native title tooltip and center the single custom update hint directly below the available-update action.
This commit is contained in:
@@ -820,7 +820,6 @@ function _syncHeaderUpdateState() {
|
|||||||
button.tabIndex = available ? 0 : -1;
|
button.tabIndex = available ? 0 : -1;
|
||||||
button.setAttribute('aria-busy', _updateCheckBusy ? 'true' : 'false');
|
button.setAttribute('aria-busy', _updateCheckBusy ? 'true' : 'false');
|
||||||
button.setAttribute('aria-label', hint);
|
button.setAttribute('aria-label', hint);
|
||||||
button.title = hint;
|
|
||||||
button.dataset.tooltip = hint;
|
button.dataset.tooltip = hint;
|
||||||
_setHeaderUpdateLabel(_updateCheckBusy ? 'Prüfen…' : (available ? 'Update verfügbar' : 'Update'));
|
_setHeaderUpdateLabel(_updateCheckBusy ? 'Prüfen…' : (available ? 'Update verfügbar' : 'Update'));
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@
|
|||||||
<div class="header-spacer" aria-hidden="true"></div>
|
<div class="header-spacer" aria-hidden="true"></div>
|
||||||
<div class="header-cluster header-utilities">
|
<div class="header-cluster header-utilities">
|
||||||
<div class="header-update-slot" id="headerUpdateSlot" aria-hidden="true">
|
<div class="header-update-slot" id="headerUpdateSlot" aria-hidden="true">
|
||||||
<button class="header-update-button" id="headerUpdateBtn" title="Nach Aktualisierungen suchen" aria-label="Nach Aktualisierungen suchen" data-tooltip="Nach Aktualisierungen suchen" tabindex="-1" disabled>
|
<button class="header-update-button" id="headerUpdateBtn" aria-label="Nach Aktualisierungen suchen" data-tooltip="Nach Aktualisierungen suchen" tabindex="-1" disabled>
|
||||||
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-download"></use></svg>
|
<svg class="header-action-icon" aria-hidden="true"><use href="#icon-download"></use></svg>
|
||||||
<span class="header-update-label">Update</span>
|
<span class="header-update-label">Update</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
+4
-3
@@ -2172,7 +2172,8 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
|
|||||||
content: attr(data-tooltip);
|
content: attr(data-tooltip);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(100% + 10px);
|
top: calc(100% + 10px);
|
||||||
right: 0;
|
left: 50%;
|
||||||
|
right: auto;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: min(240px, calc(100vw - 24px));
|
max-width: min(240px, calc(100vw - 24px));
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
@@ -2188,7 +2189,7 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
|
|||||||
white-space: normal;
|
white-space: normal;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transform: translateY(-3px);
|
transform: translate(-50%, -3px);
|
||||||
transition: opacity .14s, transform .14s;
|
transition: opacity .14s, transform .14s;
|
||||||
z-index: 80;
|
z-index: 80;
|
||||||
}
|
}
|
||||||
@@ -2196,7 +2197,7 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
|
|||||||
.header-update-button:hover::after,
|
.header-update-button:hover::after,
|
||||||
.header-update-button:focus-visible::after {
|
.header-update-button:focus-visible::after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-update-button:hover {
|
.header-update-button:hover {
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ test('header occupies its final geometry before asynchronous initialization', ()
|
|||||||
const asynchronousInitialization = appSource.lastIndexOf('\ninit().then(');
|
const asynchronousInitialization = appSource.lastIndexOf('\ninit().then(');
|
||||||
|
|
||||||
assert.doesNotMatch(updateButton, /\shidden(?:\s|>)/u);
|
assert.doesNotMatch(updateButton, /\shidden(?:\s|>)/u);
|
||||||
|
assert.doesNotMatch(updateButton, /\stitle=/u);
|
||||||
assert.ok(updateSlotIndex >= 0 && updateSlotIndex < speedWidgetIndex);
|
assert.ok(updateSlotIndex >= 0 && updateSlotIndex < speedWidgetIndex);
|
||||||
assert.match(css, /\.header-update-slot\s*\{[^}]*width:\s*0;[^}]*flex:\s*0 0 0;[^}]*overflow:\s*hidden;/su);
|
assert.match(css, /\.header-update-slot\s*\{[^}]*width:\s*0;[^}]*flex:\s*0 0 0;[^}]*overflow:\s*hidden;/su);
|
||||||
assert.match(css, /\.header-update-slot\.is-visible\s*\{[^}]*width:\s*146px;[^}]*flex-basis:\s*146px;/su);
|
assert.match(css, /\.header-update-slot\.is-visible\s*\{[^}]*width:\s*146px;[^}]*flex-basis:\s*146px;/su);
|
||||||
|
|||||||
+2
-2
@@ -2450,8 +2450,8 @@ setTimeout(async () => {
|
|||||||
const updateDialogChangelog = await wc.executeJavaScript('(() => { const title = document.querySelector(".update-release-notes-title"); const body = document.getElementById("updateReleaseNotesBody"); const titleRect = title?.getBoundingClientRect(); const bodyRect = body?.getBoundingClientRect(); return { hidden: document.getElementById("updateReleaseNotes")?.hidden, title: title?.textContent?.trim(), body: body?.textContent, gap: bodyRect && titleRect ? bodyRect.top - titleRect.bottom : null }; })()');
|
const updateDialogChangelog = await wc.executeJavaScript('(() => { const title = document.querySelector(".update-release-notes-title"); const body = document.getElementById("updateReleaseNotesBody"); const titleRect = title?.getBoundingClientRect(); const bodyRect = body?.getBoundingClientRect(); return { hidden: document.getElementById("updateReleaseNotes")?.hidden, title: title?.textContent?.trim(), body: body?.textContent, gap: bodyRect && titleRect ? bodyRect.top - titleRect.bottom : null }; })()');
|
||||||
check('Update dialog renders a compact normalized changelog', updateDialogChangelog.hidden === false && updateDialogChangelog.title === 'Changelog' && updateDialogChangelog.body === 'New in this version\\n\\nMenus and navigation\\n\\n• Added live language switching.\\n• Improved settings layout.' && updateDialogChangelog.gap <= 10);
|
check('Update dialog renders a compact normalized changelog', updateDialogChangelog.hidden === false && updateDialogChangelog.title === 'Changelog' && updateDialogChangelog.body === 'New in this version\\n\\nMenus and navigation\\n\\n• Added live language switching.\\n• Improved settings layout.' && updateDialogChangelog.gap <= 10);
|
||||||
|
|
||||||
const updateHeaderHint = await wc.executeJavaScript('(() => { const button = document.getElementById("headerUpdateBtn"); return [button?.textContent?.trim(), button?.getAttribute("aria-label"), button?.dataset.tooltip].join("|"); })()');
|
const updateHeaderHint = await wc.executeJavaScript('(() => { const button = document.getElementById("headerUpdateBtn"); const tooltip = getComputedStyle(button, "::after"); return [button?.textContent?.trim(), button?.getAttribute("aria-label"), button?.dataset.tooltip, button?.hasAttribute("title"), tooltip.left, tooltip.right].join("|"); })()');
|
||||||
check('Available update gives the header action a matching hint', updateHeaderHint === 'Update verfügbar|Update v9.9.9 verfügbar. Klicken zum Installieren.|Update v9.9.9 verfügbar. Klicken zum Installieren.');
|
check('Available update uses one centered custom tooltip below the header action', updateHeaderHint === 'Update verfügbar|Update v9.9.9 verfügbar. Klicken zum Installieren.|Update v9.9.9 verfügbar. Klicken zum Installieren.|false|73px|auto');
|
||||||
|
|
||||||
const updateDialogDismissed = await wc.executeJavaScript('document.getElementById("dismissUpdateBtn")?.click(); (() => { const overlay = document.getElementById("updateBanner"); return [overlay?.style.display, overlay?.getAttribute("aria-hidden"), document.activeElement?.id, document.querySelector(".app-header")?.inert, document.querySelector(".view.active")?.inert].join("|"); })()');
|
const updateDialogDismissed = await wc.executeJavaScript('document.getElementById("dismissUpdateBtn")?.click(); (() => { const overlay = document.getElementById("updateBanner"); return [overlay?.style.display, overlay?.getAttribute("aria-hidden"), document.activeElement?.id, document.querySelector(".app-header")?.inert, document.querySelector(".view.active")?.inert].join("|"); })()');
|
||||||
check('Update dialog closes and restores focus and background', updateDialogDismissed === 'none|true|headerUpdateBtn|false|false');
|
check('Update dialog closes and restores focus and background', updateDialogDismissed === 'none|true|headerUpdateBtn|false|false');
|
||||||
|
|||||||
Reference in New Issue
Block a user