Two inputs, one derived total. Change either field and the total recomputes via `live` - no event wiring between them.
A bill amount, a tip percentage, and a total that updates as you type in either field. The inputs and the total communicate through reactive variables, and the total automatically tracks which variables it depends on.
<div class="receipt">
<div class="receipt-header">
★ ★ ★<br>
TIP CALCULATOR
</div>
<div class="receipt-line">
<label for="bill-input">Bill</label>
<input id="bill-input" type="number" min="0" step="0.01" value="20"
_="bind $bill to me">
</div>
<div class="receipt-line">
<label for="tip-input">Tip %</label>
<input id="tip-input" type="number" min="0" step="1" value="18"
_="bind $tip to me">
</div>
<div class="receipt-rule"></div>
<div class="receipt-line receipt-total">
<span>Total</span>
<strong _="live
set total to ($bill * (1 + ($tip / 100))) as Fixed:2
put '$' + total into me"></strong>
</div>
<div class="receipt-footer">
Thank you!
</div>
</div>
The calculator is three bits of hyperscript:
bind $bill to me -- on the bill input
bind $tip to me -- on the tip % input
live -- on the total
set total to ($bill * (1 + ($tip / 100))) as Fixed:2
put '$' + total into me
bind $bill to me is two-way binding: it keeps the global reactive variable
$bill and the input's value in sync in both directions. Type in the
input, $bill updates. Set $bill from anywhere else, the input updates.
Same for $tip.
live evaluates its body once at install time and automatically tracks
which variables it reads. The total's live block reads both $bill and
$tip. Whenever either variable changes, the body re-runs and the new value lands in the element.
The as Fixed:2 conversion converts the final number into a fixed-precision string representation.