Demystifying application alerts and why you should build your own Alert component

Quan Nguyen
8 min readSep 28, 2021

--

TL;DR: A deep drive into different types of alerts, the driving force behind them and how we can and should build our own Alert component for centralizing application alerts.

If you have developed apps long enough, chances are you probably implemented a lot of alerts: Dialogs, Banners, Snackbars, BottomSheets, Local Notifications, etc. These are simply just different ways to present information to the user based on an action the user performs or when there’s something important we want the user to know. E.g. App Update, System Maintenance, etc.

So, what’s the big deal? You might ask.

Well for one, there are just too many ways to do it. This means we’d need different APIs and UIs to implement them, which might lead to imports of different third-party libraries. And when we use third-party libraries, we’d have to depend on them whenever you need to alert something. If we are not careful, things can get really messy when we have an application that can alert the user from anywhere. On top of that, the more ways to alert mean the more inconsistent your UX might become. So, you start to get the picture, right?

Believe me, I’ve done my fair share of implementing bad alerts and I am not very proud of it. I completely understand the reason behind using different types of alerts. It’s just that, sometimes it just makes things very difficult to manage. In most cases, your app might not need all of these alerts. Also, it’s always a good idea to keep things simple. How?

What we we really need is a centralized way to handle all of your application’s alert requests. Our alerts should be driven by your brand and UX instead of compromising the experience based on what’s available in third-party libraries. Also, all alerts should be consistent and blend in with the rest of the application’s UI. We should be able to fire alerts anywhere from the application without worrying importing third-party libraries to do that. On top of all this, we no longer have to compromise any of the functionalities due to limitation or API constraints imposed by those third-party libraries.

The Goal

That sounds like a really good reason to build our own alert system, right?

Below is a summary of the requirements:

  • A single and centralized component to service all alerts in an application.
  • Alerts should be fired from anywhere in an application easily.
  • Alert UIs can be expressive and consistent with the rest of the brand.
  • Having complete control of when an alert can be fired, where it is presented in the UI (E.g. top, middle, bottom) and how long it is visible to the user. (i.e. Auto-closed, manually-closed by the user)
  • Different options for handling multiple alerts in sequence. (E.g. Queuing alerts; Trumping alerts, etc.)

Sounds like there’s a lot to handle, right? Panic not. It’s not as difficult as it looks.

Let’s start with some important concepts. Understanding these will help you categorize the different types of alerts and how they should be designed.

The Concepts

  1. Importance: How important is it to alert something to the user? How would it affect the user’s experience if we didn’t show it to him? Knowing how important the information is allows us to plan and present the information to the user in a way that is beneficial to him instead of bothering him with useless information.
  2. Urgency: Do we need to show it to the user now? Can it wait until the user performs a particular action before showing it? Although it makes some sense to say that the more important the information, the more urgency it has. Unfortunately, this is not always the case because the information we show the user is based on the context of where the user is and what he’s doing at a particular point in the application.
  3. Intrusiveness: How will an alert affect the user’s ability to use the application? Can the user continue using the application when presenting with an alert or will he be completely blocked out of the application until an action is taken?
  4. Actions: Do we need the user to perform an action as part of an alert? Is it optional and can he ignore it?
  5. Duration: How long will an alert be displayed for? Is it temporary and can be auto-closed or would it require the user to manually close it?

Now that we understand the concepts around which alerts are built on. Let’s categorize our alerts:

Alert Types

  1. Feedback Alerts: These are presented to the user after he has performed an action so that he know if the action has succeeded, failed and if there’s a follow-up action the user needs to take. These alerts come in two flavors: (1) Status Feedback — short-lived auto-closed alerts whose purpose is to let the user know if his action succeeded or failed. (2) Follow-up Action Alerts — these alerts are often presented following a successful action and are typically accompanied with an optional action. These alerts can be manually closed by the user or auto-closed after a short period of display time (e.g. 3–5 seconds). Depending on the context, the alerts can block the rest of the UI until the user performs the action or close the alert.
  2. Reminders: These are typically used to remind the user of something important he needs to do while still letting the user use the app. The user can ignore less-important reminders by dismissing the alerts manually. More-important reminders will remain “sticky” until the user completes the required action. By “completing” I meant the user will have to start the action and completes it. Eg. Completing a required app update; Verifying an email; etc.
  3. Confirmations: Similar to Follow-up Action Alerts alerts with a follow-up action but different in (1) The action the user wanted to perform before seeing the confirmation can only be started after the user confirms it, thus the name “confirmation”. Whereas, the action in an Action Feedback alert is another action after the user already completes the action that prompts the feedback alert. (2) Typically a Confirmation Alert blocks the user from doing anything else until the user confirms or cancel it, whereas an Action Feedback alert is typically auto-closed or can be manually closed by the user when he starts interacting with other parts of the application.

Now that we got the requirements, the concepts and the different types of alerts we want to build. Let’s quickly look at some common use cases in an app before designing the system.

  1. Letting the user know he successfully or unsuccessfully completes an action. E.g. Showing a quick feedback to let the user know he an item has been added to his shopping cart.
  2. Showing the user what he should do next after completing an action. E.g. Alerting the user to start a conversation in a community after he successfully joins it.
  3. Asking the user to confirm a critical action. E.g. Asking the user if he wants to continue deleting his account.
  4. Remind the user to complete an action/task in an app in order to enjoy what the app has to offer. E.g. Reminding the user to verify his email the next time the user opens the app again.
  5. Blocking the user from interacting with the app until the user completes the action presented to him. E.g. Prompting the user about a required update of the app.
  6. Alerting the user when new information arrives. E.g. Displaying a new message from another user to the user.

The Design

The goal is come up with a centralized and simple API that can be consumed any where in an app. Basically what we need is an architecture that includes these high-level components.

  1. Alert Listener: A singleton that sits at the top of an application listening for alert requests and processing them one by one in a Queue-like maner. It manages the lifecycle of an alert and builds the UI that the user sees and interacts with.
  2. Generator: An asynchronous function that generates an AlertInfo object that contains an AlertDataVM object (i.e. View data) to display, and an AlertConfig object containing information about how the alert should be displayed. (i.e. closing, blocking ui, etc.)
  3. Request Channel: Used by the clients to send alert requests to the generator. The requests can be in one of the three alert categories above

Flutter Implementation

Up until this point, we’ve mainly looked at the concepts and the design of an Alert system. The benefit of going though this exercise is to help us focus on what comprises an Alert system, instead of just focusing on the HOW to implement one from the beginning.

In this section, we will look at HOW we can implement this Alert system for a Flutter application, which is probably the reason why you read this article in the first place.

In my previous articles:

Why you should consider breaking down your Flutter app into smaller components.

Designing Adaptive and Scalable Flutter Apps Using Themeable and Reusable Components

where I wrote about designing your Flutter apps using components. What I am talking about next is just an application of all of the concepts explained in those articles.

Really, this is just an application of the VCFB (View-Component Factory-BLoC) pattern introduced in the Designing Adaptive and Scalable Flutter Apps Using Themeable and Reusable Components article which explains how to create a reusable component using UI Views, Component Factory (for building the views), and BLoC (for handling business logics). Let’s see how these map to our design above:

  1. Alert Listener: This maps to the AlertComponent (factory) in the pattern which is responsible for listening for alert requests, queuing them and processing them. Based on an AlertConfig object associated with each request, it chooses the right UI view (based on the alert data and configurations) to build and uses the application’s navigator’s overlay to add an entry containing the alert UI in it.
  2. Request Channel: This is a Dart stream object that is exposed by the BLoC component for alert clients to send requests to the BLoC.
  3. Generator: This is the mapEventToState generator function of the BLoC component. The generator receives a request to show an alert in the form of an event via the Request Channel and generates a new state based on the event. The state contains a AlertViewVM object and an AlertConfig object which describes the view data and the config for the alert to be displayed by the Alert Listener, respectively.

We’re reaching the end of it. I hope you’ve learned something about alerts and will use this to build your own Alert component. If you have any questions about how to implement this, please comment below or PM me. I’d be happy to help.

Best,

Quan

--

--