Reference

States & transitions

States are the screens a project can be in. Transitions connect states by event name and attach to clickable elements in the JSX, so the project behaves as a working click-through prototype.

What a state is

Each state has a name, a block of JSX, and a frame size (see Devices, themes & zoom). The name is used in two places: it shows as the frame's header on the canvas, and it becomes the state ID that transitions point at.

States are ordered. The States panel (open it from the dock) can be drag-reordered, and that order drives the default left-to-right layout on the canvas — until you drag a frame by its name to pin it where you want. The first state in the list is the project's entry point — Play mode opens it by default when no specific state is requested.

state-list-sidebar.png

Declaring a transition

Transitions are declared from the Transitions panel (open it from the dock), which holds the list of transitions — each with a source state, a name (the event), and a target state.

transitions-section-expanded.png

Typical event names match the verb the user performs:

  • submit — button that submits a form
  • retry — "Try again" on an error state
  • open / close — dialogs and overlays
  • next / back — multi-step wizards

Nothing enforces this naming; use whichever verbs fit the feature. Each transition is just (event name) → (target state).

Attaching a transition to an element

Transitions attach to JSX through a data-transition attribute. Any clickable element — a button, a link, an interactive div — can carry the attribute:

<Button data-transition="submit">Place order</Button>
<a data-transition="open">Open settings</a>
data-transition-attribute-code.png

At runtime (in Play mode), clicking an element with a data-transition attribute looks up the matching transition and navigates to its target state. A click on an element without the attribute does nothing — exactly as it would in the real app.

Project-wide uniqueness

Every data-transition value must be unique within the project; the same event name cannot attach to two elements, even in different states. The editor enforces this and surfaces a warning when a duplicate is introduced.

The rationale is that a transition represents a single event in the feature's behaviour. If two different buttons should both navigate to the same state, declare two separate transitions (submit and confirm, both pointing at success) — this keeps the event log legible.

Transition targets

A transition points at a state by ID. Deleting the target state leaves the transition dangling; the editor shows the transition in a warning style until either the target is restored or the transition is removed. Play mode treats a click on a dangling transition as a no-op.

dangling-transition-warning.png

Reading the flow on the canvas

The canvas draws transitions as curved arrows between state frames, labeled with the event name. The arrows stay visible at every zoom level, so the overall graph is legible even when zoomed out to fit the whole project.

transition-arrows-canvas.png

Arrows can overlap on dense projects. Reorder states in the States panel to separate the common paths — the layout on the canvas follows that order — or drag the frames apart by their names. Arrows re-route live as frames move.

What transitions do not do

Transitions describe navigation only. They do not model form values, loading states, or component-local React state. The loading state that appears after submit is a separate state, with its own JSX, rather than a dynamic value held on the previous screen.

This is deliberate — Statecraft models the feature's states, not its runtime. Anything that would require mutable state belongs inside the eventual React implementation, not in the prototype.