Hotwire + Tailwind: Spinner without Javascript

by Elvinas Predkelis X

Idea and Setup

The setup is pretty straight-forward. It’s just a turbo frame with a spinner inside of it.

However, when the frame is being loaded, it looks something like <turbo-frame id="loadable" busy="" aria-busy="true"> - it has a [busy] attribute attached to it.

Turns out, it’s possible to leverage that [busy] attribute. 💆


Adding Tailwind modifiers

This is where most of the 🪄🎩 magic 🎩🪄 happens. Tailwind allows to set up custom modifiers which is exactly what we need in this case.

// tailwind.config.js

let plugin = require("tailwindcss/plugin");
module.exports = {
  // ...
  plugins: [
    plugin(({ addVariant }) => {
      addVariant("busy", "&[busy]");
      addVariant("group-busy", ":merge(.group)[busy] &");
    }),
  ],
};

Here a busy modifier is set up which is bound to the [busy] attribute. Also, group-busy is added to target the spinner inside of the parent turbo frame.


Finishing touches

Now we can just ✨sprinkle✨ some classes on some elements.

<turbo-frame id="loadable" class="group">
  <svg
    class="group-busy:inline hidden h-6 w-6 animate-spin"
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
  >
    <circle
      class="opacity-25"
      cx="12"
      cy="12"
      r="10"
      stroke="currentColor"
      stroke-width="4"
    ></circle>
    <path
      class="opacity-75"
      fill="currentColor"
      d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
    ></path>
  </svg>
</turbo-frame>

In this instance, the spinner just appears while the turbo frame is being loaded. The frame element now has a group class while the spinner now has group-busy:inline hidden classes.

Obviously, you can now style it to your liking when using the respective modifiers. For example, busy:opacity-50 will make the turbo frame transparent while loading.


Wrapping up

The main goal was to once again shake off some unnecessary Javascript from the codebase. This turned out to be a rather tidy way of doing so while keeping the simplicity of Hotwire and the flexibility of Tailwind.

We love big ideas and ambitious people

Reach out to us and let's build something great together

Schedule an exploration call