Managing Complex Waiting Experiences on Web UIs
source link: https://www.tuicool.com/articles/hit/M7fuiqB
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Managing Complex Waiting Experiences on Web UIs
W aiting is not a concept we like. We are usually stressed at every point where “waiting” touches our lives. And on the internet, “waiting” can be much more complicated than we thought it would be.
But apparently there is a long time we will have to “wait” until the tech guys solve the “speed” problem. ¯\_(ツ)_/¯
“You cannot manage what you cannot define.”
Part 1: Let’s define “waiting”!
On the Web, we frequently face the expression “loading” . I experienced that managing the “loading” experience is much more complicated than I thought, and I really had to manage it.
So, let’s define “waiting”:
In interfaces, “waiting” splits into 4 concepts which you can combine :
- Scope: Where the “waiting” happens.
- Specificity: If the “waiting” time is known.
- Interaction: If the “waiting” blocks the user or not.
- Reality: If the “waiting” is real or fake.
1. Scope
Defines where the “waiting” action happens. It may be two areas:
-
:package: Application [A]
Whole application will be loaded or some loading will affect whole application. E.g. Booting an operating system, opening a big software. -
:scissors: Component [C]
A part of an application will be loaded. E.g. Loading timeline tweets while scrolling Twitter’s feed.
2. Specificity
Defines if we know then the “waiting” will end.
-
⏭ Determinate [D]
The waiting action has a specified ending. E.g. Downloading a file, watching a movie, listening to a music, etc. -
:fast_forward: Indeterminate [I]
The waiting action does not have an ending. E.g. Streaming a live TV channel, listening to a radio, waiting for someone to write a reply to your comment, sending a request to a server, etc.
3. Interaction
Defines if the “waiting” action will block the interaction origin (user).
-
:lock: Blocking [B]
The waiting action is critical and the user shouldn’t touch specified area while something is happening. E.g. blocking user not to click “create” button again while creating something on back-end. -
:unlock: Non-blocking [N]
The waiting action is not really critical and user can touch anywhere while something is happening. E.g. Allowing user to step into a specified time while YouTube movie is loading.
4. Reality
Defines if the “waiting” action is real or not real.
-
:memo: Real [R]
The waiting action really waits for something to end in the background. E.g. User uploads their avatar to the server. -
:thought_balloon: Fake [F]
The waiting action is not really waiting but it “feels” like doing something. It’s generally for UX purposes. E.g. Wait for server to create seed data.
“Waiting” Examples
Every combination of these 4 concepts has a value on UIs.
I don’t think to add Reality concept to the combination since it doesn’t make any difference on UI aspect.
Application, Determinate, Blocking :package: ⏭ :lock:
Use cases: Splash screens.
Think of an application scope with blocking user and has a predictable ending. It’s basically a splash screen.
Splash screens are something which puts users to on hold and it doesn’t allow you to use anything while things completely set up.
In the example above, there is a progress bar that indicates the status of the waiting progress.
Info: If the “waiting” work has a predictable or specified ending (determinate) , generally “progress bars” are being used.
Application, Determinate, Non-blocking :package: ⏭ :unlock:
Use cases: Top loader, global activity indicator.
Blocking user is not friendly for your application and when the waiting is on application scope, top loaders or global activity indicators are your friend.
Note: Predictable waitings should also be considered as “determinate” even they are “indeterminate”. A page loads in maximum 1–2 seconds. Thus it’s a good UX to use a progress bar.
Application, Indeterminate, Blocking :package: :fast_forward: :lock:
Use cases: Splash screens (for mobile)
Waiting for an “indeterminate” action is generally shown as “activity indicators” which are circle loaders .
Application, Indeterminate, Non-blocking :package: :fast_forward: :unlock:
Use cases: Activity indicator, hourglass.
When you do not want to block user while something is happening on application, an activity indicator shown on screen which is generally minimal.
Component, Determinate, Non-blocking :scissors: ⏭ :unlock:
Use cases: Background loaders, percentage texts.
While you actually wait for something to load, the UI will allow you to interact with it. YouTube’s “gray loader” actually covers this case.
Component, Indeterminate, Blocking :scissors: :fast_forward: :lock:
Use cases: Ghost loaders
Ghost loaders are most popular loaders nowadays. Building user interface with faking its content makes the layout more stable in UX aspect.
Combinations without examples, not very common:
- :scissors: ⏭ :lock: Component, Determinate, Blocking: Download progress bars of browsers may be examples for that.
- :scissors: :fast_forward: :unlock: Component, Indeterminate, Non-blocking: Optimistic rendering with an activity indicator may be example for that.
Let’s summarize the combinations with a table:
Part 2: Let’s manage them!
After defining the concepts, managing them become easier.
Let’s assume we have an interface as below:
There are few simple steps to easily manage them:
1. Name every “wait”:
Naming waits is the first step you need to make. It allows you to trace and debug in complex states.
2. Collect them into a list:
The “waiting” names should be collected into an array:
Loaders should be in a global singleton loaders array. Also the names must be unique.
let waitingFor = [
"fetching sidebar",
"fetching user",
"fetching content",
"sending content",
];
3. Add and remove them:
A simple push
to the waitingFor
before the actual work starts:
// Start a new loader
waitingFor.push("logging in");
await fetch("/login");
And to remove, filter
the waitingFor
and replace it with the new state.
// End the loader await fetch("/login");
<strong>waitingFor = waitingFor.filter(l => l != "logging in");</strong>
4. Get the state of loaders:
// Are there any loaders on application scope?
return waitingFor.length > 0;
// Are there any specified loader?
return waitingFor.includes("logging in");
5. Collect progresses in a key-value store:
Keep progress information in another global singleton object.
<strong>let progresses = {};</strong>
6. Starting a progress:
Also the waitingFor
should be appended.
// Set the progress of "uploading avatar"
waitingFor.push("uploading avatar");
progresses["uploading avatar"] = { current: 249, total: 1828 };
7. Ending a progress:
waitingFor = waitingFor.filter(l => l != "uploading avatar");
const { ["uploading avatar"]: omit, ...progresses } = progresses;
// or
delete progresses["uploading avatar"];
A Vue.js Implementation: vue-wait
According the ideas above, I created a tool called “vue-wait” that manages your loaders with a declarative API and useful Vue component .
Vue-wait is an implementation for Vue to manage loaders easily. It has a very simple API.
For detailed documentation, please visit https://github.com/f/vue-wait
Thanks Fatih Acet for review.
Recommend
-
76
Waiting is not a concept we like. We are usually stressed at every point where “waiting” touches our lives. And on the internet, “waiting” can be much more complicated than we thought it would be…
-
7
Web UIs mit Kotlin Was ich am aufregendsten an Kotlin finde, ist dessen Konzeption, ein einheitliches Toolkit (Sprache + Bibliotheken + Tooling) anzubieten, sich aber auch auf die native Umgebung zu verlasse...
-
4
Feedback: UIs, Mac pains, hardware, teaching and octal It's time for more reader feedback, and some responses. Regarding the "type the exact number to continue" post...
-
8
Creating Custom UIs with Map LayersTableau’s recent release, version 2020.4, included the new Map Layers functionality, which enables you to easily la...
-
2
Microservices Composite UIs for Microservices: Vertical Slice APIs
-
5
Wasting resourcesIt’s recommended to expose the Flow<T> API from lower layers of your app hierarchy rega...
-
2
How to actually test UIsTesting techniques used by leading engineering teamsVarun VachharApr 07, 2021 — @winkerVSbecksTesting UIs is...
-
2
Getting ready for Declarative UIs — Part 3 — Why Declarative UIs on Android?
-
2
What Web Designers Can Do to Create Lightweight and Faster Mobile UIs Google now ranks websites based on how good the mobile experience is. We’re...
-
0
Repository files navigationHyperdiv Hyperdiv is a framework for rapidly developing reactive browser UI apps in Python, with built-in components, terse immediate-mode syntax, and minimal tool boilerplate.
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK