Events
Interaction is a write. A control sets a binding to a new value, and the reverse cascade carries that change into state. This page covers the practical side: clicks, typing, actions, and retry. Reversibility is the model underneath.
Buttons write to state
Button.Set(binding, newValue, content) names the binding to write and the value to write; the
closure builds the face. Pressing it runs Reactive.Set(binding, newValue). A button writes only the
binding it was handed, so its effect stays local and readable.
const count = Reactive.State(Maths.Integer)(0);
Layout.Row(() => {
const down = Maths.Subtract(count, 1);
Button.Set(count, down, () => { Content.Text('−'); });
Content.Text(count);
const up = Maths.Add(count, 1);
Button.Set(count, up, () => { Content.Text('+'); });
});
count; each button
writes one back. The framework re-runs and reconciles for you.Because the button holds a binding, the framework reasons about it. While that state is write-locked by a reverse in flight, the button disables itself. You write nothing for that.
Inputs bind two-way
A text field binds a value in both directions. Hand the input the binding; it reads and writes. What is typed flows through the binding's reverse into state, and every view of that value follows.
// both views share one state, so they stay in step
const name = Reactive.State(Text)('Ada');
Input.Text(name); // type here…
Content.Text(name); // …and this echoes it, live
The strength shows with a dotted path into a structure. A reversible path lets an
input bound to document.person.name rebuild person, rebuild document, and
set the backing state, all from one line:
Input.Text(document.person.name);
Actions write into a reverse
A Save, Undo, or Submit is a Button.Set that writes into a
Reactive.Reverse, a write-only sink whose reverse function does
the work. Pressing the button sets it; the reverse fires. A reverse stores no value, so the signal is momentary
and clears itself.
// "clear the form": a write into a reverse that resets several states
const clear = Reactive.Reverse(() => {
Reactive.Set(name, '');
Reactive.Set(email, '');
});
Button.Set(clear, true, () => { Content.Text('Clear'); });
Retry is a write
The pattern reaches error handling. A value that carries an error also carries a retry binding, and the UI wires a button to it. Pressing retry sets the flag; a reverse re-runs the failed work. This is the same mechanism as every interaction, so spinners, disabled controls, and retry come for free. Asynchronous covers where the errors come from.
One verb
To see what a control does, read the binding attached to it. It is a local declaration, right where the control
is. Interaction, asynchronous results, and retry share one verb, Set, so the same shape handles all
three.