Screencast
14. Fullpage Loading Spinner with LiveView
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