Z-Index Builder

Z-Index Builder is used to set z_index for views. It only affects sibling node ordering under same parent view, not global stacking context.

Basic Writing

After importing ZIndexBuilder, all views implementing View can call .z_index(...).

use flor::view::builder::ZIndexBuilder;
use flor::views;
use flor_lys::div::div;
use flor_lys::label::label;

let panel = div(views![
    label("Normal Content").z_index(|| 0),
    label("Floating Content").z_index(|| 10),
]);

Current signature is:

pub trait ZIndexBuilder {
    fn z_index(self, z_index: impl Fn() -> i32 + 'static) -> Self;
}

So fixed value also needs to write as closure returning i32, for example .z_index(|| 10). If layer level depends on signal, read signal in closure:

use flor::signal::{create_signal, Read};
use flor::view::builder::ZIndexBuilder;
use flor_lys::label::label;

let popup_open = create_signal(false);

let popup = label("Menu")
    .z_index(move || if popup_open.get() { 100 } else { 0 });

Relationship with class

After enabling class feature, z-* in layout class will be parsed into same set of runtime layer level values.

use flor::view::builder::ClassBuilder;
use flor_lys::label::label;

let popup = label("Menu").class("z-100");

z-auto will write 0, z-10 will write 10. z-* is special item in layout class: it won't enter Taffy layout style, but directly update ViewId's layer level value.

If you already use .z_index(...) to dynamically control layer level, don't use z-* on same view to express another fixed layer level, to avoid subsequent updates overriding each other.

Suitable Scenarios

Common use is separating temporary content and normal content in same container:

ScenarioSuggestion
Popup menuGive menu value higher than trigger button and normal content.
Floating toolbarGive toolbar stable high layer level value.
Drag previewDuring drag switch preview view to higher layer level.
Normal list itemKeep default 0, only raise when need floating or dragging.

Layer level only compares between sibling nodes. Two views with different parent views cannot achieve global covering solely through z_index; you need to put them into the same sortable parent container, or adjust the view tree structure.

Mechanism Explanation

.z_index(...) will create a reactive updater. During initialization will immediately calculate closure result once, and call current view's ViewId::set_z_index(value); afterwards when signal depended by closure updates, will write new layer level value again.

ViewId::set_z_index will:

  1. Write value to VIEW_STORAGE.view_z_index.
  2. Find current view's parent view.
  3. Re-sort parent view's child list according to sibling views' respective z_index().

Views that haven't set layer level, ViewId::z_index() returns 0.