Demo type · 08

Prototype interaction — let the reader drive the flow

Use this when a concept is a sequence of states and the reader needs to feel which moves are allowed at each step — a checkout, a traffic light, an order lifecycle, an approval queue.

This is a copyable exemplar. Lift the <section id="drive-it"> stage into a real lesson built from assets/lesson-template.html, keeping the design tokens verbatim.

1

What this format does


Some ideas only click once you poke them. A checkout has a handful of stages — cart, payment, paid, cancelled — and the whole point is that you can't skip around: you can't refund an order that was never paid, and once it's cancelled there's nowhere left to go. Describing that in a paragraph is forgettable. Letting the reader press the buttons and watch the system refuse the illegal moves makes the rule stick.

Think of it like… a board game where only certain squares connect. You roll, you move — but the board won't let you jump to a square there's no path to. The greyed-out buttons below are the squares you simply can't reach from where you're standing.

Under the hood

This is a finite-state machine. There is exactly one current state, a fixed set of events, and a transition table that maps (state, event) → nextState. Events that aren't in the table for the current state are not allowed — the prototype disables their buttons instead of silently doing nothing, so the constraint is visible, not hidden.

States with no outgoing transitions (PAID, CANCELLED) are terminal: every event button is disabled and only Reset remains. Modelling a flow this way is what stops the classic bug of refunding an unpaid order or charging a cancelled cart — the illegal path doesn't exist in the table, so it can't be taken.

2

Drive it yourself


Press an event. Watch the highlighted node move and the readout update. Buttons grey out the moment a move isn't allowed from where you are.

next pay cancel Cart CART Awaiting payment AWAIT Paid PAID · final Cancelled CANCELLED · final

The clay-filled node is where you are now. Faint nodes are unreachable from here.

Current state

CART

Items are in the basket. Nothing is committed yet.

Allowed transitions

Event log

    The whole machine in one object

    Everything the prototype does is driven by this table. The buttons read it to decide what to enable; pressing one looks up transitions[state][event] and moves there. No allowed move is hard-coded twice — the diagram, the chips, and the disabled states all come from this single source of truth.

    const machine = {
      CART:      { next: 'AWAIT', cancel: 'CANCELLED' },
      AWAIT:     { pay:  'PAID',  cancel: 'CANCELLED' },
      PAID:      {},            // terminal — no outgoing events
      CANCELLED: {}             // terminal
    };
    
    function send(state, event) {
      const next = machine[state][event];
      return next ?? state;   // reject: stay put if not in the table
    }