In-App Animated and Timed Slidedown Notifications

You can create animated and timed in-app notifications with Phoenix Liveview projects, to give you more flexibility than what flash messages can offer. This example slides a notice down from the top of the app, then eliminates the notice after 5 seconds. It gracefully handles dynamic content updates. You can enhance the feature to add id’ or class values that change how the notification is rendered, or to disappear on a clickevent.

The feature works as follows:

  • An event requires notification
  • In the event handler, change a socket.assigns.notif_active parameter value from blank to active, change the socket.assigns.notif_timer parameter value from nil to a newly assigned timer reference, and change the notif_name and notif_msg parameter values in the socket
  • The page is re-rendered with the new active class value, which triggers the css to animate the notification
  • When the timer triggers, handle the :end_notify info event to change the notif_active socket param back to blank, causing the css to hide the notification
  • For the use case of new events occurring before the timer expires, call the Process.cancel_timer/1 method synchronously in the notification event handler before updating socket assigns, so that the new content can be displayed in the notification for the full normal display time period.

This feature requires code in your .css, .ex, and .leex files

.CSS

/*Notifications*/

.notify{  
  position:absolute;
  top:0px;
  width:100%;
  height:0;  
  padding: 0;
  color:white;  
  background:rgba(0,105,217,.8);
  overflow:hidden;
  box-sizing:border-box;
  transition:height .2s;
}

#notifyType:before{
  display:block;
  margin-top:15px;  
}

.active{  
  height:40px;
  padding: 5px;
}

.LEEX
Add a div to your leex file

  <div class="notify <%= @notif_active %>" id="notify"><span id="notifyType" class=""><i>[<%= @notif_name %>]</i> <%= @notif_msg %></span></div>

  • The @notif_active assign adds the active class to the div to activate the CSS rendering
  • The @notif_name assign serves as a topic or sender tag in the displayed notification
  • The @notif_msg assign is the notification body value

.EX

  • Assign notif_timer: nil, notif_name: "", notif_msg: "", notif_active: "" to your socket on initialization
  • Activate the notification, cancel any previous timer, and activate a new timer in an event handler. In this case, using a :chat submitted event
  @impl true
  def handle_info({:chat_submitted, my_server, name, chat_msg}, socket) do
    notif_timer = socket.assigns.notif_timer
    if notif_timer != nil do
        Process.cancel_timer(notif_timer)
    end
    new_notif_timer = Process.send_after(self(), :end_notify, 5000)
    {:noreply, assign(socket, server: my_server, notif_timer: new_notif_timer, notif_name: name, notif_msg: chat_msg, notif_active: "active")}
  end

  • Handle the timer triggered signal to end the notification and mark the timer as ended:
  @impl true
  def handle_info(:end_notify, socket) do
    {:noreply, assign(socket, notif_active: "", notif_timer: nil)}
  end