We had an interesting user experience challenge on a recent project. When the system was in a particular state, the user was allowed to toggle a switch. The system would immediately acknowledge the toggle and, since it was on a local network, do so faster than the user could perceive.
Our problem was that sometimes, in situations our application couldn’t track because we didn’t have the necessary information, the server was responding negatively to the toggle. Our challenge: how to communicate that yes, we got your click, but we can’t actually toggle the underlying item right now.
We first sought out as much information as we could to make sure we were actually visibly disabling the switch when we knew that it couldn’t be toggled. After implementing a few of these cases, we were still left with a few cases where the server simply did not provide us enough information to tell whether our switch-flip would succeed or not.
We knew that, in these cases and possibly others we weren’t yet aware of, we had to make the switch give the user positive feedback that it was flipped correctly. We also wanted to reflect the correct state when the server sent its negative response.
Because the response was received with effectively no latency, even if we pre-flipped the switch by toggling its state in the user interface when the request was sent, then updated it with the negative message from the server, users couldn’t see any change. It happened so fast that the animations swallowed any indication that anything had happened.
We reasoned that the way to solve this particular problem was to make sure the animation could be seen.
We started out by pre-flipping the switch. We still immediately sent the message to the server—we didn’t want to impact the responsiveness of the action the switch caused. But when we received the response from the server, we delayed the Redux action that would actually move the switch in the user interface by a few hundred milliseconds.
For the most common case where the switch flip is acknowledged, this looks exactly the same to the user. The switch still flips immediately when the user clicks it. When the acknowledgement comes in, it updates the switch state a very short time later to precisely the same state, causing no change—not even a re-render.
But for the case where the server responds negatively to the switch flip, the user experience is very different. Now the user sees the switch flip over and stay there briefly, then flip back. It’s now immediately clear to the user that we acknowledged their intent, but could not fulfill it.
Taking care of little details like this helps overcome unavoidable behavior that is otherwise frustrating to users—”I’m clicking, but nothing’s happening!” It clearly communicates that we’re on their side, but we can’t actually help them right now. It’s important to always acknowledge your user’s intent in these cases, because a user who knows the system understands their intent is a happy user.