Screencast

14. Fullpage Loading Spinner with LiveView

async beginner component spinner

I recently worked with Phoenix LiveView's async tasks and wanted a better way to show loading states. While you can use local spinners, sometimes you need to block the entire UI during processing. In this screencast, I'll show you how to create a reusable full-page loading spinner component that smoothly fades in and prevents user interaction.

def fullpage_spinner(assigns) do
  ~H"""
  <div phx-mounted={JS.transition({"transition-all ease-out duration-300", "opacity-0", "opacity-100"})}
       class="fixed bg-gray-900 bg-opacity-50 inset-0">
    <!-- spinner content --> 
  </div>
  """
end

Managing Async Tasks with LiveView's AsyncResult

ou might find this valuable if you're dealing with long-running operations in LiveView. I like this approach of using the AsyncResult module to handle loading, success, and failure states elegantly. The video goes deeper into implementing proper state management for async operations.

alias Phoenix.LiveView.AsyncResult

def mount(_params, _session, socket) do
  {:ok, assign(socket, loader: AsyncResult.ok(%{}))}
end

def handle_event("start-task", _, socket) do
  {:noreply, socket 
    |> start_async(:long_task, fn -> Process.sleep(3000) end) 
    |> AsyncResult.loading(:loader)}
end

Blocking UI Interactions in Phoenix LiveView

Combining LiveView's JS commands with Tailwind transitions to create smooth UI blocking. The screencast demonstrates how to properly handle body scroll locking and fade transitions while keeping the code clean and reusable.

<div
  phx-mounted={JS.add_class("overflow-hidden", to: "body")}
  phx-remove={JS.remove_class("overflow-hidden", to: "body")}
  class="fixed inset-0 overflow-hidden">
  <!-- spinner implementation -->
</div>

What you'll learn:

  • How to create a reusable full-page loading spinner component
  • Managing async task states using LiveView's AsyncResult module
  • Implementing smooth fade transitions with Phoenix.LiveView.JS
  • Proper handling of body scroll locking during loading states
  • Combining Tailwind CSS with LiveView components
  • Best practices for blocking UI during async operations