Let's say you are in charge of building the UI of Twitter, how many states do you think that UI could be in? One? Two? Five? Ten?
Usually, we identify at least one state, the Ideal State, this is what most users see most of the time, in Twitter it's when you have a list of tweets with their authors and the avatar of each one, and the media included in the tweets (images, links, video, audios, etc.).
Most commonly the next state we tend to identify is the Loading State, this is when our application is loading the data or the code (when using code splitting).
If you are lucky enough you have also identified the Loading Error State which mean our app can handle a case when something failed to load, this could happen if the user is offline or the server returned an error (4xx or 5xx).
The vast majority of the products stop designing states at this point, then you start the development and realize you need another state, because what happens if the user had no tweets? You need an Empty Data State too to show something nice when there are no content, maybe to invite the user to create content.
If our Twitter app has a way to search for a tweet we may found a case where there are no results, this means another state, what we need more is an Empty Results State to represent how should the UI look like when there is no content because we couldn't find anything.
Let's continue developing the product, while you are on it you realize you need another state again, because what happens if part of the data has already loaded? Are you going to wait until everything is ready or are you going to start rendering part of the UI? Implementing a Partially Loaded State is the best user experience, because why not show the data you already have while you continue fetching more data? As an example once you have a Tweet you can render it while you continue fetching the replies of that tweet (Twitter does this).
Then you continue building your product again, just to ask yourself what happens if the user tweet a short message? Or a long one? Or another with only of emojis? And what about non ASCII characters like Kanji's or accent marks? You need to start thinking in a Weird Data State, think all the possible edge cases and design for it, as an example Spanish sentences requiere higher line heights due the accents.
Ok, let's go back to building the product, we are building the form to submit a tweet, then your API returns an error, or the user forgot the write the message, or is offline, what should happen in that case? You need yet another state, I call this the User Error State, this is how to show validation error, network errors or API errors, basically error generated after the action of a user, which are usually different than Loading Error State because are limited to an small area and not the whole UI.
The form is working. The user can create the tweet and we show something if an error happens, but the API is not immediate, it will take at least a few milliseconds to confirm the tweet was sent, what should we do meanwhile? You have two options, the ideal one is to implement an Optimistic UI where the UI it updated before the API process the request and it rollback the changes when an error occurs, the other option is to show a User Action Loading State, this usually is done showing a spinner or another loading indicator and disable the form until the API returns a response (to avoid duplicated request if it takes too long).
If we go for the optimistic UI we could also have a Pending Optimistic UI State, this is something apps like Slack do, they show your message immediately in the chat but with a disabled color (gray-ish) so you know the message has not been sent yet, once the API confirms the success the message change to the normal state.
Ok, we have almost everything, the user load the data, can tweet, can see errors and loading states, let say the user leave the app open for a while without being really using it, what should happen when our app recovers the focus? Because a lot of time has passed we may want to revalidate our Server-State with the API to get the latest tweets, but we should show somehow that we are doing that so the user can expect it, this means yet another UI state! We now need a Revalidating State, we could make as iOS and show a little spinner somewhere along the old data to while we finish the revalidation, Twitter load it in background and let you know there is more data, GitHub Mobile use the iOS way and show the spinner and replace the data after it loads.
And with all of this we are finally ready to ship our product, we end up with up to 11 different states our UI can be in, a great designer think about all of them since the beginning, most designers will probably think and 4~5 of them and let the developer figure out the rest or manually ask the designer to create them, a great developer will remember the designers they need to think all of this states.
The final list of states is:
- Ideal State
- Loading State
- Loading Error State
- Empty Data State
- Empty Results State
- Partially Loaded State
- Weird Data State
- User Error State
- User Action Loading State
- Pending Optimistic UI State
- Revalidating State