mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +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 classes = new Set();
|
||||||
const style = {
|
const style = {
|
||||||
removeProperty(name) {
|
removeProperty(name) {
|
||||||
|
// Like CSSStyleDeclaration: 'z-index' also clears style.zIndex.
|
||||||
delete this[name];
|
delete this[name];
|
||||||
|
delete this[name.replace(/-([a-z])/g, (_, c) => c.toUpperCase())];
|
||||||
},
|
},
|
||||||
getPropertyValue: () => '',
|
getPropertyValue: () => '',
|
||||||
};
|
};
|
||||||
@@ -191,3 +193,55 @@ test('two quick header presses snap a floating panel back; slow or distant ones
|
|||||||
f.restore();
|
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. */
|
/** Z ladder: panels promote within [100, 139]; voice pill 150, toast 200, clean-view-exit 300. */
|
||||||
const PANEL_Z_BASE = 100;
|
const PANEL_Z_BASE = 100;
|
||||||
const PANEL_Z_MAX = 139;
|
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. */
|
/** Pointer travel before a header press becomes a drag that lifts a portable panel out. */
|
||||||
const DRAG_THRESHOLD_PX = 4;
|
const DRAG_THRESHOLD_PX = 4;
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +44,8 @@ const FLOATING_STYLE_PROPERTIES = [
|
|||||||
'bottom',
|
'bottom',
|
||||||
'width',
|
'width',
|
||||||
'height',
|
'height',
|
||||||
|
// A docked panel takes the rail's stacking, not a floating window's.
|
||||||
|
'z-index',
|
||||||
];
|
];
|
||||||
|
|
||||||
function clamp(value, min, max) {
|
function clamp(value, min, max) {
|
||||||
@@ -264,6 +273,9 @@ export class PanelPositionControls {
|
|||||||
if (Boolean(pos.floating) !== Boolean(portable)) return;
|
if (Boolean(pos.floating) !== Boolean(portable)) return;
|
||||||
if (portable) {
|
if (portable) {
|
||||||
panelEl.classList.add('panel-floating', 'panel-draggable');
|
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)) {
|
if (Number.isFinite(pos.width)) {
|
||||||
panelEl.style.width = `${clamp(
|
panelEl.style.width = `${clamp(
|
||||||
Math.round(pos.width),
|
Math.round(pos.width),
|
||||||
@@ -337,7 +349,7 @@ export class PanelPositionControls {
|
|||||||
const promoted = [...document.querySelectorAll('.panel-draggable')]
|
const promoted = [...document.querySelectorAll('.panel-draggable')]
|
||||||
.filter((el) => el.style.zIndex)
|
.filter((el) => el.style.zIndex)
|
||||||
.sort((a, b) => Number(a.style.zIndex) - Number(b.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) {
|
for (const el of promoted) {
|
||||||
el.style.zIndex = String(z);
|
el.style.zIndex = String(z);
|
||||||
z += 1;
|
z += 1;
|
||||||
|
|||||||
@@ -117,6 +117,9 @@
|
|||||||
#right-context-rail > .panel-floating {
|
#right-context-rail > .panel-floating {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: auto;
|
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);
|
max-height: calc(100vh - 12px);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
flex: none;
|
flex: none;
|
||||||
|
|||||||
Reference in new issue
Block a user