Skip to main content

Node

Node is the concrete tree value returned from a widget's build() method.

Every widget in the catalog eventually becomes a Node variant such as Node::Row, Node::Text, or Node::Container. In day-to-day app code, you usually do not construct the enum variants by hand. Instead, you build a widget struct and call .into_node() or use a widget's build(...) method.

Use Node when you need a common type for heterogeneous children or conditional returns. Do not start from Node when learning the framework. Most app authors should think in widgets first and treat Node as the unified output format.

Example

use fission::core::ui::{Container, Node, Text};

fn status_chip(online: bool) -> Node {
let label = if online { "Online" } else { "Offline" };
Container::new(Text::new(label).into_node()).into_node()
}

Here Node is useful because the function returns one shared tree type even though the content may vary.

Variant overview

VariantPayload typeMeaningNotes / default behavior
Node::Row, Node::Column, Node::Grid, Node::ZStackLayout widgetsOrdinary layout structure.These are the variants most app code produces.
Node::Text, Node::Image, Node::Video, Node::IconDisplay widgetsVisual content nodes.Often appear as leaves or small subtrees.
Node::Button, Node::TextInput, Node::Checkbox, Node::Switch, Node::Radio, Node::SliderInput widgetsInteractive controls with built-in semantics.Prefer these over low-level gesture wiring when they fit.
Node::Container, Node::Clip, Node::Composite, Node::TransformWrappersStyling, clipping, and visual adjustment around another node.Good for composition without inventing new widgets.
Node::Overlay, Node::Positioned, Node::SafeArea, Node::LazyColumnSpecialized layout helpersSolve specific structural problems.Reach for them when the problem matches the helper directly.
Node::CustomCustomNodeEscape hatch for custom lowering and custom render behavior.Most app authors should avoid this until there is a clear need.

How to work with it

The most common use of Node is as a container type in Vec<Node> fields or as the return type from helper functions. That keeps the rest of your code flexible: one child can be a Text, another can be a Container, and both still fit in the same layout list.

What you usually should not do is manually match on many Node variants in application code. If you feel pushed in that direction, it often means the composition boundary belongs in widgets or selectors instead.

Specific advice

Stay at the widget level as long as possible. Calling .into_node() at the edge of a helper is normal; building everything by hand as raw enum variants is usually harder to read and easier to misuse.

The one important exception is advanced custom work. When you need a new kind of lowered surface, Node::Custom(...) is the official escape hatch through CustomNode.

Widget, CustomNode, and Builder.