Enhance Rails 8 Form UX with a Submit Spinner Using Turbo’s aria-busy Attribute

Edu Depetris

- Dec 29, 2024
  • Ux
  • Turbo
  • Ruby On Rails
  • Tailwind Css
Let’s provide a quick UX win for our users by adding a spinner loader to the “Add” button after it is pressed. To demonstrate this, we’ll use the form introduced in the previous article.

Leveraging Turbo’s aria-busy Attribute

Turbo automatically adds the aria-busy attribute to HTML and Turbo Frame elements when navigation is in progress. Have a look here to see what else Turbo adds.

In our previous example, we created a simple form to add items. Check it out here. During form submission, Turbo sets aria-busy="true" on the <form> element. Once navigation completes, Turbo removes the aria-busy attribute.

Displaying a Spinner with Tailwind CSS

We’ll use the aria-busy state along with Tailwind’s ARIA states to display a spinner loader while navigation is in progress.

Step 1: Modify the Submit Button

First, replace the form.submit with a standard form.button. We’ll pass a block containing two elements: the label “Add” and an SVG spinner.

Step 2: Toggle Visibility Based on aria-busy

Next, we’ll show or hide the “Add” label and the spinner SVG based on the aria-busy attribute. The SVG spinner will be hidden by default and displayed when aria-busy="true".

Step 3: Add the group Class to the Form

Finally, add the group class to the form to target the aria-busy state of the form and apply Tailwind classes accordingly.

Our new button will look like this [Commit

<%= form_with(model: item, class: "group", id: dom_id(item)) do |form| %>
  <!-- other content here -->

  <%= form.button type: :submit, class: "rounded-lg py-2 px-3 bg-blue-600 text-white font-medium cursor-pointer" do %>
    <span class="group-aria-busy:hidden">Add</span>
    <svg class="hidden group-aria-busy:block motion-reduce:hidden animate-spin h-6 w-6 text-white" 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>
  <% end %>
<% end %>

Here's an example with the final result

form-with-spinner.mp4 322 KB


By following these steps, we’ve enhanced the form’s user experience by providing visual feedback during form submission, all without writing any JavaScript.

Happy Coding!