mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix(ui): floating windows stack above the docked rail panels
A floating window restored after a reload had no z-index, and the z ladder renumbered from 101, so the docked DISPLAY panel (#pp-toggles, z 110) painted over it. The ladder now starts at 111 (PANEL_Z_FLOATING_FLOOR), a restored window is promoted like a lifted one, docking drops the promotion, and floating panels get a CSS floor of 111. Tests fail on the old code. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
e6c2c812f9
commit
f7456f2436
3 files changed
+70
-1
No files matched your search
@@ -15,7 +15,9 @@ function fixture() {
|
||||
const classes = new Set();
|
||||
const style = {
|
||||
removeProperty(name) {
|
||||
// Like CSSStyleDeclaration: 'z-index' also clears style.zIndex.
|
||||
delete this[name];
|
||||
delete this[name.replace(/-([a-z])/g, (_, c) => c.toUpperCase())];
|
||||
},
|
||||
getPropertyValue: () => '',
|
||||
};
|
||||
@@ -191,3 +193,55 @@ test('two quick header presses snap a floating panel back; slow or distant ones
|
||||
f.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('a restored floating window stacks above the docked DISPLAY panel (z 110)', () => {
|
||||
const f = fixture();
|
||||
try {
|
||||
const panel = f.element();
|
||||
panel.id = 'street-level-panel';
|
||||
f.owner._portablePanels.set('street-level-panel', {
|
||||
panel,
|
||||
min: { width: 320, height: 280 },
|
||||
dockOnCollapse: true,
|
||||
});
|
||||
f.store.set(
|
||||
'godsEyeView.v8.panelPos.street-level-panel',
|
||||
JSON.stringify({
|
||||
left: 900,
|
||||
top: 200,
|
||||
width: 420,
|
||||
height: 600,
|
||||
floating: true,
|
||||
}),
|
||||
);
|
||||
f.owner._restorePanelPosition('street-level-panel', panel);
|
||||
assert.equal(panel.classList.contains('panel-floating'), true);
|
||||
assert.ok(Number(panel.style.zIndex) > 110, `z ${panel.style.zIndex}`);
|
||||
f.owner.dockPanel('street-level-panel');
|
||||
assert.equal(panel.style.zIndex, undefined, 'docking drops the promotion');
|
||||
} finally {
|
||||
f.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('renumbering the z ladder never drops a window below the docked panels', () => {
|
||||
const f = fixture();
|
||||
try {
|
||||
const windows = [f.element(), f.element(), f.element()];
|
||||
windows.forEach((node, index) => {
|
||||
node.classList.add('panel-draggable');
|
||||
node.style.zIndex = String(130 + index);
|
||||
});
|
||||
globalThis.document.querySelectorAll = (selector) =>
|
||||
selector === '.panel-draggable' ? windows : [];
|
||||
f.owner._panelZCounter = 139;
|
||||
const top = f.element();
|
||||
top.classList.add('panel-draggable');
|
||||
f.owner._promotePanelZ(top);
|
||||
for (const node of [...windows, top])
|
||||
assert.ok(Number(node.style.zIndex) > 110, `z ${node.style.zIndex}`);
|
||||
assert.ok(Number(top.style.zIndex) > Number(windows[2].style.zIndex));
|
||||
} finally {
|
||||
f.restore();
|
||||
}
|
||||
});
|
||||
@@ -12,6 +12,13 @@ const PANEL_POSITION_STORAGE_VERSION = 'v8';
|
||||
/** Z ladder: panels promote within [100, 139]; voice pill 150, toast 200, clean-view-exit 300. */
|
||||
const PANEL_Z_BASE = 100;
|
||||
const PANEL_Z_MAX = 139;
|
||||
/**
|
||||
* Lowest z a promoted (dragged or floating) panel may take: above every panel
|
||||
* docked in a rail, the highest of which is #pp-toggles at 110 (controls.css).
|
||||
* Renumbering restarts here, so a floating window never slips under DISPLAY.
|
||||
* Keep in step with `#right-context-rail > .panel-floating` in controls.css.
|
||||
*/
|
||||
const PANEL_Z_FLOATING_FLOOR = PANEL_Z_BASE + 11;
|
||||
/** Pointer travel before a header press becomes a drag that lifts a portable panel out. */
|
||||
const DRAG_THRESHOLD_PX = 4;
|
||||
/**
|
||||
@@ -37,6 +44,8 @@ const FLOATING_STYLE_PROPERTIES = [
|
||||
'bottom',
|
||||
'width',
|
||||
'height',
|
||||
// A docked panel takes the rail's stacking, not a floating window's.
|
||||
'z-index',
|
||||
];
|
||||
|
||||
function clamp(value, min, max) {
|
||||
@@ -264,6 +273,9 @@ export class PanelPositionControls {
|
||||
if (Boolean(pos.floating) !== Boolean(portable)) return;
|
||||
if (portable) {
|
||||
panelEl.classList.add('panel-floating', 'panel-draggable');
|
||||
// A restored window must stack above the docked rail panels too, not
|
||||
// only one that was lifted or clicked this session.
|
||||
this._promotePanelZ(panelEl);
|
||||
if (Number.isFinite(pos.width)) {
|
||||
panelEl.style.width = `${clamp(
|
||||
Math.round(pos.width),
|
||||
@@ -337,7 +349,7 @@ export class PanelPositionControls {
|
||||
const promoted = [...document.querySelectorAll('.panel-draggable')]
|
||||
.filter((el) => el.style.zIndex)
|
||||
.sort((a, b) => Number(a.style.zIndex) - Number(b.style.zIndex));
|
||||
let z = PANEL_Z_BASE + 1;
|
||||
let z = PANEL_Z_FLOATING_FLOOR;
|
||||
for (const el of promoted) {
|
||||
el.style.zIndex = String(z);
|
||||
z += 1;
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
#right-context-rail > .panel-floating {
|
||||
position: fixed;
|
||||
inset: auto;
|
||||
/* Above every docked rail panel (#pp-toggles is 110). PanelPositionControls
|
||||
promotes floating windows from this floor (PANEL_Z_FLOATING_FLOOR). */
|
||||
z-index: 111;
|
||||
max-height: calc(100vh - 12px);
|
||||
margin: 0;
|
||||
flex: none;
|
||||
|
||||
Reference in new issue
Block a user