-
Notifications
You must be signed in to change notification settings - Fork 0
Core Concepts
Nestix separates UI structure from platform rendering. The core runtime manages elements, props, reactive values, layout composition, and lifecycle callbacks. Renderer components translate those runtime events into host operations.
An Element is a node in the Nestix component tree. It stores:
- the component identity;
- type-erased props;
- parent and child relationships;
- typed context values;
- lifecycle callbacks;
- an optional host handle supplied by a renderer.
Elements are reference-counted handles. Cloning an Element clones the handle to
the same node, not the node itself.
A component is a type implementing Component. Most components are written as
functions with #[component]:
#[component]
fn Label() -> Element {
layout! { Text("Hello") }
}When an element mounts, Nestix calls the component's on_mount implementation.
The macro-generated implementation downcasts the element props, calls the user
function, and mounts the returned output under the current element.
Props are named-field structs annotated with #[props]. The macro:
- implements the
Propstrait; - wraps normal fields in
PropValue<T>; - generates a typed builder;
- supports required fields, default fields, positional start fields, grouped setters, and nested fields.
Props are type-erased inside Element, then downcast when a component mounts.
PropValue<T> is either:
- a plain value, stored in an
Rc<T>; - a signal-backed value, read by calling the signal.
Component code reads props with .get():
let class_name = props.class.get();When that read happens inside an effect or computed value, signal-backed props participate in reactive updates.
Signals are readable reactive values. State<T>, Computed<T>, and
Readonly<T> implement Signal.
Reading a signal inside a tracked context records a dependency. Updating state notifies dependent effects and computed values.
Layout represents zero, one, or many elements. The layout! macro builds
elements, prop values, child layouts, conditionals, and keyed lists using a
component-oriented syntax.
layout! {
Div {
Text("One")
Text("Two")
}
}Nestix does not know what a host node is. A renderer component should:
- create a platform object such as a DOM node;
- register
element.on_place(...)to insert or move that object; - call
element.provide_handle(...)so children can find their host parent or predecessor; - register
element.on_unmount(...)to clean up; - use effects to synchronize reactive props to the host object.
This boundary is what makes nestix reusable for different UI targets.