Unifying error states across Twitter.
During my internship at Twitter, I worked on creating a consistent solution for error states to be implemented in our Horizon design system. This project was a great learning experience for me because I had to learn to work within constraints, prioritize user needs, and design a solution that could be implemented across the board.
Audit of mobile error states
Design solution for connectivity errors
Design solution for geoblocked states
Documentation of work in Horizon design system
Understanding Error States
Initially, I was assigned to design an edge case error message for overcapacity errors. But, after digging into it, we realized there wasn’t any existing documentation on error states within our design system.
Before I was given this project, error states had always gone over my head (as they do with many people). In order to even begin, I needed to learn everything I could about error states. I read tons of articles
and examined how other platforms have tackled this problem.
Some key questions I wanted to answer for context:
When specifically does an overcapacity error occur?
What does a user have to do in order to make this happen?
How can a user get out of this state?
After doing tons of research and auditing error states in other apps, I understood guidelines for what error states are and what makes a good error state experience for a user.
Some guidelines around error states:
Basically, an error state occurs when something goes wrong in the app
They don’t always have to be boring, but “fun” messaging should still serve a purpose
The primary goal is to help a user understand what's going on and how to get out of it
A user’s experience when encountering various errors across Twitter is currently confusing, unclear, and inconsistent. The goal of my project was to create an error state solution to be incorporated in our design system that would give users a clear experience when encountering errors across the app.
In order to understand the error state problems in Twitter specifically, I did an audit of existing errors in our mobile app on iOS, Android, and RWEb. I asked my coworkers for screenshots, and went on airplane mode and 2g network to recreate the experience. And can I just say, 2g network is so. slow.
Categorizing and Prioritizing
After I had a pile of screenshots of errors I collected from others and from my own testing, I realized many of these errors had commonalities either in cause or call to action. Because I was able to identify common ground between different types of errors, I felt it would be easier to create solutions based on these commonalities rather than trying to create one solution to encompass all error types at once. So, I organized the audit and broke it down into three main buckets or “types” of error states.
Backend errors: when someone experiences an unknown error due to an internal bug.
Information validity errors: when someone tries to access information that is no longer valid or available.
User errors (i.e.: connectivity errors): when someone is connected to very slow or no internet and information fails to load.
After categorizing all the errors I identified, I worked with a product manager and another designer to decide on a focus for my project. Because of the limited amount of time I had during my internship, I realized I wouldn’t be able to cover all error states, and wanted to tackle an area that I could manage and execute.
We gathered data from prior research surrounding errors and connectivity issues, and decided to focus our efforts on network connectivity errors, aka user errors for two reasons:
We are absolutely sure of the cause and call to action (when applicable)
These are the error messages that our users encounter most frequently
Goal: design a solution for network connectivity errors that can be expanded to other error states later on.
With a palatable goal in mind, I began exploring design solutions. Because there weren’t any existing components for error states in place, it was hard to find a place to start. Instead, I thought about the closest thing we already had to error states in our design system, which is empty states (see below).
My first iteration was based off of what already exists for empty states because I felt the two situations are similar where content that should be there, isn’t.
What are the functional vs. emotional needs of a user when errors occur?
In what situations are a call to action necessary vs. just a notification?
Iterations and Considerations
I took my work to critique and tried different lockups of text, buttons, and icons to find the right combination that would convey a clear message and call to action.
I wanted to design the network connectivity error experience from start to end, not just the error message screen. So, I added an in app notification at the start to indicate when a user is offline. The error screen has a call to action where the user can retry once they are connected to the internet.
Part of the challenge of designing within a system was that I had to think about the consistency between the components throughout the entire offline experience, not just the error message. I thought about similar experiences in the app like loading states, and worked with the designer who was working on progress indicators to make sure we were using unified elements.
Throughout the design process, I also worked with a content strategist to decide on the right messaging to include in our error states. Though a designer’s work guides a user’s experience with errors, I felt that the messaging is just as important for someone’s understanding and plays a crucial role in conveying Twitter’s brand in a world as minimal as error states.
In order to differentiate error states from empty states, I removed the headline on the page because it felt unnecessary and even celebratory. I also added an icon for the call to action button lockup to make it clear that it’s a retry button. The icon is what’s typically used for retry buttons, so users would quickly understand the purpose of the button.
This project was an awesome challenge for me. Previously, I had little experience designing within strict constraints like in a design system, let alone had experience designing FOR a design system. I was so shocked that the design team at Twitter trusted me with such a large task.
Initially, it was daunting, but with the help of my mentor and by collaborating with other designers, I was able to set clear goals for myself on the project and deliver them by the end.
When given a project with a wide scope, find an aspect to narrow in on
Set guidelines and goals, and inform the people you’re working with on what they are
Even when working on an edge case, how it fits into the entire app and experience matters
Not every project comes from a sexy vision, but it still serves an important part in a user’s experience
What I love about this project was that it started as a bug fix, and evolved into what it was because the deeper I dug into the problem, the more there was to cover.
Even within the short time of my internship, I was able to apply the structure from network connectivity errors to a geoblocked error state for Twitter broadcast events.
The solution I shipped only scrapes the surface of error states within Twitter’s design systems, but I’m happy it opened the conversation.