Components

Components are first-class language constructs. The component keyword declares a composable unit with props, state, events, and an optional view tree.

Declaration syntax

tape
component Name {
    prop label: *u8;
    prop size: i64 = 48;

    var count: i64 = 0;

    state hovered: bool = false;

    event on_click();

    slot content;

    @dispatch fn paint(ctx: *u8, x: i32, y: i32, w: i32, h: i32);

    @tape { ui.drawable(); }

    fn increment() {
        count = count + 1;
    }

    view {
        widgets.Label { text: label; }
    }
}

Keywords inside components

KeywordPurpose
prop name: Type = default;Immutable input from parent
var name: Type = init;Mutable reactive state
state name: bool = init;Boolean interaction flag (targetable from #style)
event name(params);Typed callback channel
slot name;Named insertion point for child content
@dispatch fn name(params);Vtable slot for polymorphic dispatch
@dispatch(required) fn ...;Required dispatch (must be implemented)
@tape { ... }Compile-time code generation block
view { ... }Declarative visual tree
fire event_name(args);Emit an event to the parent’s handler

state and #style

state fields are bool-only and targetable from #style via :name pseudo-selectors:

tape
component Button {
    state hovered: bool = false;
    state active: bool = false;
}
tape
#style
Button {
    bg: #444444;
    :hovered { bg: #555555; }
    :active { bg: #333333; }
}

The compiler verifies that each :name matches a state declaration — unmatched selectors are a compile error.

Component constraint type

The *component[...] type constrains a pointer to components implementing specific dispatches:

tape
fn render(widget: *component[@dispatch fn paint(ctx: *u8, x: i32, y: i32, w: i32, h: i32)]) {
    widget.paint(ctx, 0, 0, 100, 100);
}

The is operator checks constraints at runtime:

tape
if (widget is *component[@dispatch fn paint(ctx: *u8, x: i32, y: i32, w: i32, h: i32)]) {
    widget.paint(ctx, x, y, w, h);
}

View tree syntax

View trees contain component instances, control flow, and slot references:

tape
view {
    ui.Column {
        if (show_header) {
            widgets.Label { text: "Header"; }
        }
        for (item in items) {
            ListItem { data: item; on_click: handle_select; }
        }
        content;
    }
}

Props bind with name: expr;. Slots fill with slot name { children };.


For full details on props, events, lifecycle, views, and dispatch, see the Components section.

Last modified: