<root>
<root> renders its children as a separate top-level UI tree on the
window, wherever it sits in your React tree. It fills the window and floats
above the app's own UI, which makes it the place for modals, toasts and
overlays declared next to the state that drives them. It is the on-screen
counterpart of <surface>, which renders a tree into a
texture.
Usage
const [open, setOpen] = useState(false);
<node>
<button onClick={() => setOpen(true)}>
<text>Open</text>
</button>
{open && (
<root
name="modal"
style={{
alignItems: "center",
justifyContent: "center",
backgroundColor: "#000000aa",
}}
>
<node
style={{ padding: 20, borderRadius: 12, backgroundColor: "#24283b" }}
>
<text>Hello from an overlay</text>
<button onClick={() => setOpen(false)}>
<text>Close</text>
</button>
</node>
</root>
)}
</node>;Mounting and unmounting the <root> is the whole open and close mechanism.
Default style
A <root> starts with this style, which its own style overrides property
by property:
{ width: "100%", height: "100%", flexDirection: "column", globalZIndex: 1 }It has no alignment or gap of its own, so its children stretch across its
width. Center them with alignItems and justifyContent, as above. (The
main window tree differs: it centers top-level elements and spaces them
16px apart.)
How it behaves
- Detached from its parent's layout. Its React parent's size, padding,
overflowclipping, transforms and opacity don't affect it. In React it is an ordinary child: context, state and handlers work as usual, and it unmounts with its parent. - On the window's UI camera. It renders on the default UI camera, like
the main tree. There is no attribute to target another camera or window;
for UI on a texture or a 3D mesh, use
<surface>. - Stacking. Roots and the main tree (
globalZIndex0) are ordered byglobalZIndex, so the default1floats above the app. Two roots with the same value have no defined order: give overlays that can be open together distinct values. See Z-index. - Click-through. The root itself is never hit by the pointer, background included: clicks and hover on its empty area reach the app and the 3D scene beneath. Its children are ordinary pickable elements.
- Props. A
<root>takesstyle,name,sharedTagandkey. State styles and event handlers on it are ignored with apropIgnoredwarning; put them on a child.
Blocking modals
To keep the app beneath from reacting while a modal is open, make the backdrop a blocking child that fills the root:
<root>
<node
style={{
flexGrow: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#000000aa",
focusPolicy: "block",
}}
>
<node style={dialogStyle}>{/* … */}</node>
</node>
</root>To close on an outside click, give the backdrop an onClick and the dialog
focusPolicy: "block", so clicks inside the dialog don't reach the
backdrop. See Focus policy.
Devtools
The Nodes tab of the devtools shows one tree at a
time and has a root selector: main for the window tree, plus one entry per
mounted <root>, labelled with its name (or root#N without one). Name
your roots to find them there. The devtools panel is itself a <root>,
kept above every app overlay.
Limits
- Window UI camera only; no target camera or window.
- Layer styles on the
<root>itself (filter,backdropFilter,morphFilter,transform3d,cache) have no effect, and itsopacityfades only its own background. Wrap the content in a full-size child and style that. - The root is its own UI root for shared elements:
a
sharedTagnever pairs a node inside a root with one outside it.
See <root> in the element reference.
bevy-react