Skip to content

Core Concepts

wirelessEye edited this page Jul 2, 2026 · 4 revisions

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.

Element

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.

Component

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

Props are named-field structs annotated with #[props]. The macro:

  • implements the Props trait;
  • wraps normal fields in PropValue<T>, unless marked #[props(raw)];
  • 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

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.

Signal

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

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")
    }
}

Renderer Boundary

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.

Clone this wiki locally