My new favorite technique for showing loading indicators in Livewire buttons

I've been getting a lot of questions lately about showing loading indicators on buttons in Livewire and Flux. Turns out with a dash of Tailwind, good loading indicators aren't that hard to build!

Here's a preview of the new button loading functionality I added to Flux yesterday:

🔥 If you haven't purchased your copy of Flux yet, we're still running the launch sale. It's almost 50% off during launch for unlimited projects forever. Pretty hard to beat. Grab your Flux license here →

Before we dive into how you can implement something like this in Livewire, here's a look at how you use it in Flux:

Yeah, that's it. Just add "wire:click" to a button like you normally would, and Flux will inject some extra code to show a loading indicator when a request is out to the server.

Flux also adds loading indicators to submit buttons using "type="submit"".

What makes a good loading button?

First: you don't want the loading indicator to increase the size of the button. It looks sloppy and can shift other elements around on a page.

Second: you don't want the indicator to show up if the request is too short. It's important to add a slight delay so that the you don't end up with a "blip" of a loading indicator.

And third: you want to prevent a user from accidentally clicking the button twice while one request is already out to the server.

Now that we have some requirements for our button, let's tackle the implementation.

Most of the magic is made possible by the following Livewire syntax: wire:loading.attr="data-loading".

Read more about wire:loading →

By adding this to a button element, Livewire will set the data-loading attribute on the button while a request is out to the server.

This enables us to style other elements based on the presence of data-loading.

Let's use Tailwind's arbitrary variants to fade out the text inside the button so we can show a loading indicator on top of it. This way, the button won't change size when it's loading:

If you're unfamiliar with the syntax above and think it looks hideous, you're not wrong. But trust me, like everything in Tailwind, you will fall in love with it as you use it more and feel its power.

Now, all that's left is absolute positioning a loading icon using the same technique as above:

That's a lot of code for a tiny screenshot. Here's a GitHub gist for easier viewing →

To make things smoother, we can transition the opacity of each element with Tailwind's "transition-opacity" utility:

Now, you should have a smooth looking loading indicator like the following:

Because there is a short transition on showing the loading indicator, a Livewire request that happens too fast, won't show a jarring "blip" anymore. It will either be undetectable, or be a more pleasant, brief, fade.

If you want to only show the indicator on slower requests, you can use Tailwind's "delay-*" utility to delay the transition and only show it if a request is taking too long:

Lastly, we will want to disable pointer-events on the button while it's loading so that click events don't trigger a duplicate request:

In the next version of Livewire, I will likely add data-loading attributes to loading elements by default, but until then, wire:loading.attr should do the trick!

Again, if you are using Flux, update to version 1.0.3, and your buttons will have all of this automatically. If you're not using Flux, this technique is not that hard to apply to your own button components.

Happy loading stating,

-Caleb

Comments

Popular posts from this blog

🥳 Flux UI is now live!

C# lists, Regression Testing, and much more!

New Livewire Data Tables series is here!