R1.03.4state transition failuredesign

Transitions between states fail more often than the states themselves

Aliases: state transitions · state-machine edges · enter and leave

What it is

Every cell in a state table is a snapshot. What the user lives through is the path between cells. A request starts while focus is still on the button; loading ends in success or failure; focus may or may not remain; an empty frame may flash in between — none of that lives in the snapshot. State transition failure is more common than a missing cell, because a path has to decide what is preserved, what is announced, and whether you can go back.

A complete catalog with no arrows still breaks at runtime. Watch the edges, not the dots.

Why it happens

A snapshot can be reviewed on its own: disabled on an artboard is obvious at a glance. A transition carries time and cause: who triggered it, how long it takes, which properties must hold, which edge failure takes. Focus, scroll position, typed text, and how far a screen reader had read are luggage on the path. Default implementations often unmount the subtree on entering loading, the luggage drops, and the user must find the control again. If empty is treated as a mandatory frame between loading and data, the success path flashes “nothing here” and looks like a fault.

Error recovery is the edge most often un-drawn: after failure, do we stay on error until retry, or silently return to default? The two edges mean different products, yet the catalog may already contain an “error” cell and look complete. The dots are there. The edges are not.

Where it stops holding

Pure CSS hover with no async and no cross-frame process is just enter and leave; it does not need its own item. Continuous quantities that change every frame in a game or a visualization are not a discrete state machine; drawing edges will fake the model. Route-level unmount (leaving the page) is owned by page lifecycle, not by the component’s internal transitions; if the component is conditionally unmounted inside the page, it still must say who receives focus before it goes. Motion duration is not a transition spec; the state promises at both ends of the duration are.

Applying it

  • Draw allowed edges beside the state table: which cells may follow which. Forbid illegal edges (empty → pressed) explicitly.
  • For every async edge, write what is kept on enter (focus, input, scroll) and what assistive technology is told on leave.
  • Force a primary button from default into loading, then branch to success and to error, under slow network and failure injection. Record whether focus holds and whether empty flashes.
  • How to check: every edge that appears in the recording must exist on the diagram, and luggage (focus, input) must be kept as promised. An extra empty flash or a dropped focus is a catalog without transitions.

Related

  • Same group: R1.03.1 Every component needs a complete interactive state set · R1.03.2 Loading, empty, and error are the states most often left unspecified · R1.03.3 Missing states get improvised during implementation · R1.03.5 Overlapping states need an explicit priority rule · R1.03.6 States must be controllable and observable from outside the component
  • Nearby: R3.02 Focus management · R3.05 Render blocking and layout shift
  • Search terms: state transition failure · state machine · focus restoration

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/R1.03.4