Skip to content

Macro Reference

wirelessEye edited this page Jun 29, 2026 · 11 revisions

Macro Reference

Most Nestix syntax is implemented by procedural macros from nestix-macros and re-exported by nestix.

#[component]

Turns a function into a component type.

#[component]
fn App() -> Element {
    layout! { Text("Hello") }
}

Supported function parameters:

  • none;
  • &Props;
  • &Props, &Element.

Generic component type parameters are supplied with generics(...):

#[component(generics(T))]
fn Show<T: Clone + 'static>(props: &ShowProps<T>) -> Element {
    todo!()
}

#[props]

Turns a named-field struct into component props and generates a builder.

Container attributes:

  • debug: use the struct's Debug implementation for type-erased prop debug formatting.
  • bounds(...): bounds used by generated impls.
  • extensible(TraitName, WrapperTraitName): generate an extension trait and builder wrapper trait for prop composition.
  • group(name => [field_a, field_b, ...]): generate a builder method that sets multiple normal fields to the same value.

Field attributes:

  • default: use Default::default().
  • default = expr: use a custom default.
  • start: make the field positional.
  • extends(TraitName, WrapperTraitName): embed another prop group through its extension trait and builder wrapper trait.
  • extends(TraitName, WrapperTraitName(args...)): pass start arguments to an extended builder.

layout!

Creates elements and layouts.

layout! {
    Div(.class = "main".to_string()) {
        Text("Hello")
        if visible.get() {
            Panel
        }
        for item in items.clone() where key = |item| item.id {
            Row(.item = item)
        }
    }
}

Special forms:

  • $(expr): splice an element or iterable of elements.
  • yield Component: create the item inside the generated computed closure.
  • binding @ Component: write the component handle into a state.
  • [captures] |args| { ... }: child factory syntax.

build_props!

Builds a props struct using the generated builder.

let props = build_props!(TextProps("Hello"));

let props = build_props!(ButtonProps(
    .disabled = false,
    .on_click = callback!(|| log::info!("clicked")),
));

Named values are converted through prop_value!.

prop_value!

Converts a value into PropValue<T>.

let value = prop_value!("Hello".to_string());
let value = prop_value!(computed!([state] || state.get()));

closure!

Builds a closure after cloning requested captures.

let handler = closure!([count] || count.set(count.get() + 1));
let named = closure!([label: props.label] || label.get());

When a capture list is present and the closure is not already move, the macro adds move so the closure owns the cloned locals.

Capture forms:

  • [name]: clone name into a local with the same name.
  • [alias: expr]: clone expr into alias.

For simple path, field, method call, reference, cast, and unary expressions, the macro can infer the local name. Complex expressions need alias: expr.

callback!

Builds a Shared<dyn Fn(...) -> _> from closure syntax.

let on_click = callback!([count] || count.mutate(|value| *value += 1));
let remove = callback!([items] |key: &str| items.mutate(|items| {
    items.shift_remove(key);
}));

Use it for prop callbacks and renderer event adapters.

computed!

Creates a reactive computed signal after applying closure! capture handling.

let label = computed!([count] || format!("Count: {}", count.get()));

Equivalent shape:

let label = computed(closure!([count] || format!("Count: {}", count.get())));

effect!

Registers an effect after applying closure! capture handling.

effect!([element] || {
    log::debug!("{:?}", element.handle());
});

The effect runs immediately and reruns when tracked signal reads change. It returns an effect handle; call cancel() on the handle to stop future reruns.

scoped_effect!

Registers an effect that is canceled automatically when an element unmounts.

scoped_effect!(element, [props.value] || {
    log::debug!("{:?}", value.get());
});

The first argument is the element scope. The remaining input uses the same capture-handled closure syntax as effect!.

Clone this wiki locally