Blog

Flash Messages in Rails 7 using Tailwind CSS, Stimulus, and ViewComponent

George Tobias
October 11, 2023

Flash messages are a crucial part of any web application, providing feedback to users after performing certain actions. Here we’ll walk you through building flash messages in a Rails 7 application using Tailwind CSS for styling, Stimulus for interactivity, and ViewComponent for modular UI elements.

Prerequisites

Before we begin, make sure you have the following installed:

Step 1: Create a New Rails Project

Run the following command to generate a new application that uses Tailwind CSS for styling:


$ rails new flash_messages --css=tailwind
$ cd flash_messages

This also automatically installs our much needed Hotwire goodness in Stimulus (and Turbo). Check out this post if you’re looking for more ideas in setting up your application for front-end development.

Step 2: Create a Flash Message Component

ViewComponents allow you to create modular, reusable UI elements. Let’s generate a component for our flash messages:


$ rails generate component FlashMessage type message

create  app/components/flash_message.rb
invoke  tailwindcss
create    app/components/flash_message.html.erb

This will create the FlashMessageComponent class with a corresponding view template. Optionally, you can move these files inside a folder to allow your view components to be more organized (and namespaced):


# app/components/flash_message/component.rb
# app/components/flash_message/component.html.erb

Step 3: Implement the Flash Message Component

We will want to handle the different types of flash messages, and assign corresponding styles for each of them. With that, our component will now look something like this:

app/components/flash_message/component.rb:


# app/components/flash_message/component.rb
module FlashMessage
  class Component < ViewComponent::Base
    attr_reader :type, :message

    def initialize(type:, message:)
      @type = type
      @message = message
    end
    
    private

      def color_classes
        case type
        when :success
          'bg-green-100 border-green-400 text-green-700'
        when :error
          'bg-red-100 border-red-400 text-red-700'
        when :warning
          'bg-yellow-100 border-yellow-400 text-yellow-700'
        when :notice
          'bg-blue-100 border-blue-400 text-blue-700'
        else
          'bg-gray-100 border-gray-400 text-gray-700'
        end
      end
  end
end

app/components/flash_message/component.html.erb:


<!-- app/components/flash_message/component.html.erb -->
<div class='relative flex px-4 py-3 space-x-2 border <%= color_classes %>' role='alert'>
  <strong class='font-bold'><%= message[:title] %></strong>
  <span class='pl-5'>
    <%= heroicon 'x-mark', options: { class: 'w-6 h-6 fill-current', role: 'button' } %>
  </span>
</div>

You may use your favorite icon library as well (i.e. font-awesome), but I’ve found heroicons more fun to work with on Tailwind. There’s also a heroicon gem which will allow you to use a nice helper method to render your heroicon SVG’s. To make this available to your components, you may create a parent component class that includes your view helpers and have your components inherit from it:


# app/components/application_component.rb
class ApplicationComponent < ViewComponent::Base
  include ApplicationHelper
  include HeroiconHelper
end

# app/components/flash_message/component.rb
module FlashMessage
  class Component < ApplicationComponent
    # ...
  end
end

Step 4: Create the Flash Messages Partial

Create a partial for rendering flash messages in app/views/shared/_flash_messages.html.erb and add it in application.html.erb:


<!-- app/views/shared/_flash_messages.html.erb -->
<% if flash.any? %>
  <div class='inset-0 p-6 items-start justify-end'>
    <div class='flex flex-col items-center justify-center'>
      <% flash.each do |type, message| %>
        <%= render FlashMessage::Component.new(type: type, message: message) %>
      <% end %>
    </div>
  </div>
<% end %>

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
  <!-- ... -->
  <body>
    <%= render 'shared/flash_messages' %>
    <!-- ... -->
  </body>
</html>

Step 5: Set Up the Stimulus Controller

Stimulus will handle the interactivity of our flash messages. Generate a Stimulus controller:


$ rails generate stimulus FlashMessage

create  app/javascript/controllers/flash_message_controller.js

Open app/javascript/controllers/flash_message_controller.js and add the following code:


// app/javascript/controllers/flash_message_controller.js
import { Controller } from '@hotwired/stimulus'

// Connects to data-controller='flash-message'
export default class extends Controller {
  connect() {
    setTimeout(() => {
      this.element.remove();
    }, 5000) // Remove flash message after 5 seconds
  }

  close() {
    this.element.remove()
  }
}

Add the following attributes to your flash messsage elements to connect it to the stimulus controller:


<!-- app/views/shared/_flash_messages.html.erb -->
<% if flash.any? %>
  <div data-controller='flash-message' class='inset-0 p-6 items-start justify-end'>
    <!-- ... -->
  </div>
<% end %>

<!-- app/components/flash_message/component.html.erb -->
<!-- ... -->
  <%= heroicon 'x-mark', options: { 'data-action': 'click->flash-message#close', class: 'w-6 h-6 fill-current', role: 'button' } %>
<!-- ... -->

Step 6: Implement Flash Messages in Controllers

In your controllers, set up flash messages like this:


# app/controllers/some_controller.rb
def create
  # ...
  flash[:message] = 'Record was successfully created'
  flash[:type] = :success
  redirect_to some_path
end

def update
  # ...
  flash[:message] = 'Record was successfully updated'
  flash[:type] = :success
  redirect_to some_path
end

def destroy
  # ...
  flash[:message] = 'Record was successfully deleted'
  flash[:type] = :error
  redirect_to some_path
end

Step 7: Test It Out!

Start your Rails server and navigate through your application. Try performing actions that trigger flash messages to see them in action.

Conclusion

Congratulations! You have successfully implemented flash messages in your Rails 7 application using Tailwind CSS, Stimulus, and View Components. By combining these tools, you can easily create modular and interactive flash messages for your web application. This approach allows for clean separation of concerns and promotes code reusability, making it easier to maintain and extend your application in the future.

If you need any help with your Rails Application and development please reach out to us and we are happy to help.

Happy coding!