Format text with XState (Part 2)

Last updated June 22, 2021 by Jacob Paris

This is part 2 of a series on modelling UI components in XState. To view the previous entry in the series, read XState Text Formatting Part 1

In the previous article, we explored using a parallel state machine to track three distinct formatting features of a word processor: bold, italic, and underline

Each of those buttons operated independently of one-another. In this article, we'll look into modelling how a word processor would let a user select the text alignment. There are four possible states of the alignment

  • Left
  • Center
  • Right
  • Justify

While the alignment operates independently of the bold, italic, and underline states, the alignment directions are not independent of one-another.

They act like a group of radio buttons, where selecting one inherently unselects another, in the same way that enabling 'bold.on' unselects 'bold.off'. For that reason, we can model them as finite states.

A state machine showing bold, italic, underline, and alignment as parallel states

By clicking any of the left, right, center, or justify buttons, we want to transition to that state. There is no un-selecting here though, so each state will have only three transitions pointing to each of the other states

A state chart with states for left, center, right, and justify; with transitions from any to each of the others

Example: https://xstate.js.org/viz/?gist=364dea11f6cc0e1692ca139085f41fae

There is a many-to-many relationship between these states. We can simplify this model by understanding two things about it:

  • Every state is connected to every other state
  • A transition with a specific event always terminates at the same state

Those facts allow us to lift events up from the individual sub-state to the parent state, and model it as four one-to-one relationships. Now no matter which state it is in, the RIGHT event will transition to the 'align.right' state and so on for the rest of them.

A state chart showing the different alignment states, where the transitions are from the parent to each of its children

This state chart is functionally identical to the previous, with one exception: clicking LEFT while in the 'align.left' state will now cause a self-transition. Any entry action on the state will fire again on such a self transition, which might not be expected behaviour, but for most cases shouldn't be an issue.

Example: https://xstate.js.org/viz/?gist=b020d1096efd3dbc3aa9868894604392

The next part in the series is here at XState Text Formatting Part 3

References

Constructing the user interface with state charts (Addison Wesley, 1999)

XState Documentation