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
| Variant | Payload type | Meaning | Notes / default behavior |
|---|---|---|---|
Node::Row, Node::Column, Node::Grid, Node::ZStack | Layout widgets | Ordinary layout structure. | These are the variants most app code produces. |
Node::Text, Node::Image, Node::Video, Node::Icon | Display widgets | Visual content nodes. | Often appear as leaves or small subtrees. |
Node::Button, Node::TextInput, Node::Checkbox, Node::Switch, Node::Radio, Node::Slider | Input widgets | Interactive controls with built-in semantics. | Prefer these over low-level gesture wiring when they fit. |
Node::Container, Node::Clip, Node::Composite, Node::Transform | Wrappers | Styling, clipping, and visual adjustment around another node. | Good for composition without inventing new widgets. |
Node::Overlay, Node::Positioned, Node::SafeArea, Node::LazyColumn | Specialized layout helpers | Solve specific structural problems. | Reach for them when the problem matches the helper directly. |
Node::Custom | CustomNode | Escape 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.
Related
Widget, CustomNode, and Builder.