The reason why it’s not reactive is that the html function embeds the two elements (<button> and <i>) in a parent <span>.
The viewof mechanism requires the HTML element a) to have a .value property and b) to emit an input event on every value change (more details here: GitHub - observablehq/stdlib: The Observable standard library., eg if the HTML element is a button, the expected event is click. As we now have a span, we have to dispatch an input event).
I don’t know if there is a simple and clever way to make it reactive. What I would do:
viewof makeColours = {
const button = html`<button>Generate some colours</button>`;
const control = html`${button}<i>this can take a few seconds to respond</i>`;
button.onclick = e => {
e && e.preventDefault(); // to avoid dispatching the 'click' event outside
control.dispatchEvent(new CustomEvent('input'));
};
control.value = button.value;
return control;
}
For click events you can dispatch an input event with the help of Object.assign:
viewof makeColours = Object.assign(html`<button>Generate some colours</button>
<i>this can take a few seconds to respond</i>`, {
value: '',
onclick(e) { this.dispatchEvent(new Event('input')) }
})