🐛 Fix problems with z-index

This commit is contained in:
alonso.torres
2026-03-25 13:14:35 +01:00
parent 28b4c14b95
commit a5d908629b
5 changed files with 5297 additions and 24 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -505,3 +505,19 @@ test("BUG 13415 - Grid layout overlay is not removed when deleting a board", asy
await workspacePage.hideUI();
await expect(workspacePage.canvas).toHaveScreenshot();
});
test("BUG 13822 - Problems with z-index", async({
page
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockGetFile("workspace/get-file-13822.json");
await workspacePage.goToWorkspace({
fileId: "7fd33337-c651-80ae-8007-c37410926e0f",
pageId: "af41758c-e196-8138-8007-c36f805c3f6d",
});
await workspacePage.waitForFirstRenderWithoutUI();
await expect(workspacePage.canvas).toHaveScreenshot();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -266,6 +266,30 @@ impl FocusMode {
}
}
/*
* Sort by z_index descending (higher z renders on top).
* The sort is stable so if the values are equal the index for the children
* has preference.
* When changing this method check the benchmark
*/
fn sort_z_index(tree: ShapesPoolRef, element: &Shape, children_ids: Vec<Uuid>) -> Vec<Uuid> {
if element.has_layout() {
let mut ids = children_ids;
if element.is_flex() && !element.is_flex_reverse() {
ids.reverse();
}
ids.sort_by(|id1, id2| {
let z1 = tree.get(id1).map(|s| s.z_index()).unwrap_or(0);
let z2 = tree.get(id2).map(|s| s.z_index()).unwrap_or(0);
z2.cmp(&z1)
});
ids
} else {
children_ids
}
}
pub(crate) struct RenderState {
gpu_state: GpuState,
pub options: RenderOptions,
@@ -2436,30 +2460,7 @@ impl RenderState {
element.children_ids_iter(false).copied().collect()
};
// Z-index ordering
// For reverse flex layouts with custom z-indexes, we reverse the base order
// so that visual stacking matches visual position
let children_ids = if element.has_layout() {
let mut ids = children_ids;
let has_z_index = ids
.iter()
.any(|id| tree.get(id).map(|s| s.has_z_index()).unwrap_or(false));
if element.is_flex_reverse() && has_z_index {
ids.reverse();
}
// Sort by z_index descending (higher z renders on top).
// When z_index is equal, absolute children go above
// non-absolute children
ids.sort_by_key(|id| {
let s = tree.get(id);
let z = s.map(|s| s.z_index()).unwrap_or(0);
let abs = s.map(|s| s.is_absolute()).unwrap_or(false);
(std::cmp::Reverse(z), !abs)
});
ids
} else {
children_ids
};
let children_ids = sort_z_index(tree, element, children_ids);
for child_id in children_ids.iter() {
self.pending_nodes.push(NodeRenderState {

View File

@@ -1460,6 +1460,7 @@ impl Shape {
}
}
#[allow(dead_code)]
pub fn has_z_index(&self) -> bool {
matches!(
&self.layout_item,