refactor: remove dimmer overlay, add cyan border to preview popover

ANSI colors make the overlay content readable without dimming. Removed
preview-dimmer, liftHoveredTile(), tile--previewing/item--previewing —
all dead code now. Added var(--accent) 2px border to .preview-popover
for visual separation.
This commit is contained in:
Brian Krabach
2026-03-29 18:44:55 -07:00
parent b3b2165524
commit bf76affef2
4 changed files with 13 additions and 74 deletions
+1 -37
View File
@@ -127,7 +127,7 @@ let _notificationPermission = 'default';
let _pollFailCount = 0;
let _previewPopover = null;
let _previewTimer = null;
var _previewDimmer = null;
var _previewSessionName = null; // track by NAME, not DOM element
// ─── DOM helpers ──────────────────────────────────────────────────────────────
@@ -465,8 +465,6 @@ function renderSidebar(sessions, currentSession) {
});
}
// Re-apply z-index lift after innerHTML rebuild (preview survives re-renders)
if (_previewSessionName) liftHoveredTile();
}
const SIDEBAR_KEY = 'muxplex.sidebarOpen';
@@ -606,8 +604,6 @@ function renderGrid(sessions) {
updatePillBell();
}
// Re-apply z-index lift after innerHTML rebuild (preview survives re-renders)
if (_previewSessionName) liftHoveredTile();
}
// ---------------------------------------------------------------------------
@@ -638,12 +634,6 @@ function showPreview(name) {
hidePreviewDOM();
_previewSessionName = name;
// Dimmer
var dimmer = document.createElement('div');
dimmer.className = 'preview-dimmer';
document.body.appendChild(dimmer);
_previewDimmer = dimmer;
// Full-window overlay
var popover = document.createElement('div');
popover.className = 'preview-popover';
@@ -653,9 +643,6 @@ function showPreview(name) {
document.body.appendChild(popover);
_previewPopover = popover;
// Lift the original tile above dimmer
liftHoveredTile();
// Auto-scroll to bottom (prompt area)
popover.scrollTop = popover.scrollHeight;
@@ -663,22 +650,6 @@ function showPreview(name) {
document.addEventListener('click', _previewClickHandler, true);
}
function liftHoveredTile() {
// Remove any existing lift class from all tiles/items
document.querySelectorAll('.tile--previewing, .item--previewing').forEach(function (el) {
el.classList.remove('tile--previewing', 'item--previewing');
});
if (!_previewSessionName) return;
var el = document.querySelector(
'.session-tile[data-session="' + _previewSessionName + '"]'
);
if (el) el.classList.add('tile--previewing');
var item = document.querySelector(
'.sidebar-item[data-session="' + _previewSessionName + '"]'
);
if (item) item.classList.add('item--previewing');
}
// hidePreviewDOM: removes the visual elements only (no render trigger)
function hidePreviewDOM() {
document.removeEventListener('click', _previewClickHandler, true);
@@ -686,13 +657,6 @@ function hidePreviewDOM() {
_previewPopover.remove();
_previewPopover = null;
}
if (_previewDimmer) {
_previewDimmer.remove();
_previewDimmer = null;
}
document.querySelectorAll('.tile--previewing, .item--previewing').forEach(function (el) {
el.classList.remove('tile--previewing', 'item--previewing');
});
}
// hidePreview: full cleanup including timer and session name
+1 -13
View File
@@ -967,7 +967,7 @@ body {
position: fixed;
z-index: 500;
background: var(--bg-secondary);
border: 1px solid var(--border);
border: 2px solid var(--accent);
border-radius: 8px;
padding: 16px 20px;
/* Cover most of the viewport — centered with margin */
@@ -991,19 +991,7 @@ body {
overflow-x: hidden;
}
.preview-dimmer {
position: fixed;
inset: 0;
z-index: 499; /* behind popover (500), above everything else */
background: rgba(0, 0, 0, 0.55);
pointer-events: none; /* clicks pass through — don't block mouseleave */
}
.session-tile.tile--previewing,
.sidebar-item.item--previewing {
position: relative;
z-index: 500; /* same as popover — above dimmer */
}
/* ============================================================
Responsive overlay sidebar at <960px
+5 -21
View File
@@ -2075,13 +2075,12 @@ test('hover preview popover works for both grid tiles and sidebar items', () =>
'must handle sidebar items too');
});
test('hover preview popover has dim overlay and highlights hovered element', () => {
test('hover preview popover uses cyan border and no dimmer', () => {
const source = fs.readFileSync(
new URL('../app.js', import.meta.url), 'utf8'
);
assert.ok(source.includes('preview-dimmer'), 'must create dimmer overlay');
assert.ok(source.includes('tile--previewing'), 'must lift grid tile above dimmer');
assert.ok(source.includes('item--previewing'), 'must lift sidebar item above dimmer');
assert.ok(source.includes('preview-popover'), 'must create popover');
assert.ok(!source.includes('preview-dimmer'), 'must NOT use dimmer overlay (removed)');
});
test('hover preview delay is 1500ms (not 350ms)', () => {
@@ -2092,31 +2091,16 @@ test('hover preview delay is 1500ms (not 350ms)', () => {
assert.ok(!source.includes(', 350)'), 'old 350ms delay must be removed');
});
test('hover preview uses full-window overlay with text wrapping', () => {
test('hover preview uses full-window overlay with click-to-navigate', () => {
const source = fs.readFileSync(
new URL('../app.js', import.meta.url), 'utf8'
);
assert.ok(source.includes('_previewSessionName'), 'must track by session name');
assert.ok(source.includes('liftHoveredTile'), 'must re-lift tile after renders');
assert.ok(source.includes('scrollHeight'), 'must auto-scroll to bottom');
assert.ok(source.includes('preview-dimmer'), 'must have dim overlay');
assert.ok(source.includes('ontouchstart'), 'must be desktop-only');
assert.ok(source.includes('_previewClickHandler'), 'must have click-to-navigate handler');
// Must NOT have repositionPreview (old side-positioned approach)
assert.ok(!source.includes('repositionPreview'), 'must NOT have repositionPreview (old approach)');
});
test('renderGrid and renderSidebar re-lift hovered tile after innerHTML rebuild', () => {
const source = fs.readFileSync(
new URL('../app.js', import.meta.url), 'utf8'
);
// renderGrid should call liftHoveredTile after innerHTML
const gridFn = source.substring(source.indexOf('function renderGrid'), source.indexOf('function renderGrid') + 1500);
assert.ok(gridFn.includes('liftHoveredTile'), 'renderGrid must re-lift tile after render');
// renderGrid should NOT have the old _previewPopover guard
assert.ok(!gridFn.includes('if (_previewPopover) return'),
'renderGrid must NOT skip renders while preview active (old approach caused bugs)');
assert.ok(!source.includes('preview-dimmer'), 'must NOT have dimmer (removed — ANSI colors are readable without it)');
});
test('ansiToHtml converts SGR codes to styled spans', () => {