From 4a03f834591a63cff33f80f8b1c6d8c83612485a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Sun, 18 Oct 2026 11:38:02 +0300 Subject: [PATCH] APDU list + detail: hover and the detail header follow the theme tints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - the detail header used --bg-input in dark mode (plus a light-only #dbeafe override), so it only matched the list selection in the light theme; it now uses var(--selected-bg) — the same variable as the selected row — so the two are in sync in both themes (light unchanged) - .apdu-entry:hover used --bg-panel (a grey in the same family as the GET RESPONSE pair rows); both themes now set --hover-bg — the accent at 16% (dark) / 10% (light), a translucent tint that stacks with whatever the row's background is — and a single hover rule uses it: hovering tints the row blue, lighter than the selection and a different hue from the pair rows. The rules stay ordered .apdu-pair → :hover → .selected, so hovering the selected row keeps its selection colour - Node tests pin the hover variable per theme, the hover rule (and that the old grey rule is gone) and the detail header's variable; 540 Python + 80 Node tests - SW cache simtrace-analyser-v91 (cosmetic, no version bump) --- frontend/index.html | 7 ++++--- frontend/sw.js | 2 +- frontend/tests/style.test.js | 13 +++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index cb41589..af1792d 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -20,6 +20,7 @@ --bg-input: #334155; --selected-bg: #1e3a8a; /* a blue tint, so a selected row stands out from the GET RESPONSE pair rows */ + --hover-bg: rgba(59, 130, 246, 0.16); /* a slight blue on hover */ --border: #475569; --text: #e2e8f0; --text-muted: #94a3b8; @@ -54,6 +55,7 @@ --bg-panel: #e5e7eb; --bg-input: #ffffff; --selected-bg: #dbeafe; + --hover-bg: rgba(59, 130, 246, 0.10); --border: #d1d5db; --text: #1f2937; --text-muted: #6b7280; @@ -149,7 +151,7 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(- .apdu-list { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 8px; } .apdu-entry { display: flex; gap: 12px; padding: 3px 12px; border-bottom: 1px solid var(--bg-panel); cursor: pointer; align-items: baseline; } .apdu-entry.apdu-pair { background: var(--pair-row); } -.apdu-entry:hover { background: var(--bg-panel); } +.apdu-entry:hover { background: var(--hover-bg); } .apdu-entry.selected { background: var(--selected-bg); } .apdu-time { color: var(--text-muted); font-family: monospace; white-space: nowrap; min-width: 80px; } .apdu-type { color: var(--text); font-weight: 600; min-width: 150px; } @@ -182,8 +184,7 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(- .splitter:hover::after, .splitter.active::after { background: radial-gradient(circle, var(--text) 1px, transparent 1px); background-size: 6px 6px; } .splitter:hover, .splitter.active { background: var(--accent); } .apdu-detail .detail-empty { padding: 24px; color: var(--text-muted); text-align: center; } -.detail-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; background: var(--bg-input); border-bottom: 1px solid var(--border); } -[data-theme="light"] .detail-header { background: #dbeafe; } +.detail-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; background: var(--selected-bg); border-bottom: 1px solid var(--border); } .detail-header strong { font-size: 13px; } .decrypt-strip { padding: 6px 12px; border-top: 1px solid var(--border); background: var(--bg-panel); font-size: 12px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; } .decrypt-strip input { background: var(--bg-input); color: var(--text); border: 1px solid var(--border); border-radius: 4px; padding: 3px 8px; font-family: monospace; width: 260px; } diff --git a/frontend/sw.js b/frontend/sw.js index cab5863..3c1c6db 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simtrace-analyser-v90'; +const CACHE = 'simtrace-analyser-v91'; const PRECACHE = [ 'index.html', diff --git a/frontend/tests/style.test.js b/frontend/tests/style.test.js index a153f1c..fa5cc34 100644 --- a/frontend/tests/style.test.js +++ b/frontend/tests/style.test.js @@ -37,6 +37,19 @@ test('the APDU selection is a blue tint in both themes', () => { assert.doesNotMatch(src, /--selected-bg: var\(--bg-input\)/); }); +test('the APDU hover is a slight blue tint in both themes', () => { + assert.match(src, /\.apdu-entry:hover \{ background: var\(--hover-bg\); \}/); + assert.match(src, /--hover-bg: rgba\(59, 130, 246, 0\.16\);/); // dark + assert.match(src, /--hover-bg: rgba\(59, 130, 246, 0\.10\);/); // light + // The hover must not fall back to the pair rows' grey or the selection. + assert.doesNotMatch(src, /\.apdu-entry:hover \{ background: var\(--bg-panel\); \}/); +}); + +test('the detail header follows the list selection in both themes', () => { + assert.match(src, /\.detail-header \{[^}]*background: var\(--selected-bg\);/); + assert.doesNotMatch(src, /\[data-theme="light"\] \.detail-header/); +}); + // ── trace topbar layout ──────────────────────────────────────────────── test('the view selector sits over the side panel at the panel width', () => {