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.

a control exposes a binding interaction sets it the reverse does the rest

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.

Live, on this page. Two buttons write to one piece of state. Press them.
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('+'); });
});
The step values are derived from 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 binding is the wiring. Both views stay in step because they share it.

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);
Deep two-way binding from one path. Types shows how the reversible path is built.

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'); });
For several effects at once, point a button at a reverse. It fans the write into a tree of state changes.

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.