DEV Community

Cover image for Tailwind Carousel in Rails 7
Hartmut B.
Hartmut B.

Posted on

Tailwind Carousel in Rails 7

After being absence for a while, I recently began to reshape my Rails skills.

A basic Rails7-setup now includes TailwindCSS and TurboFrames.
I designed a simple Website providing a carousel as eye-catcher. Sure – you can copy the code from Tailwind Elements, install the tw-elements javascript-library and anything runs out of the box.

But that's not very rubyish. Each time you want to change something, you have to touch the source-code. I like the approach to have a configuration file, providing input-data for a helper to create the carousel on the fly.

What defines a Carousel

As shown in the Cover Photo (which is taken from the Tailwind Elements Page, we need

  • an image file
  • a title
  • a short description
  • a link to other content

Configuration in config/carousel.yml

It seems only natural to put anything in a yaml-config-file. Lets create /config/carousel.yml

---
- :first:
    :link:  first
    :image: dizzy-analyst.png 
    :title: Our amazing Approach
    :text:  Explore our unique Solution for all your Problems.
- :second:
    :link:  option
    :image: dizzy-woman.png 
    :title: Feedback
    :text:  We encourage you to provide critical feedback.

Enter fullscreen mode Exit fullscreen mode

The image-files have to be copied into /app/assets/images! Its assumed, that the links just point to anchors on the same page.

The Controller

Assuming, you have setup a User-Resource and want to place the carousel on the Index-Page.

# app/controller/users_controller.rb

class UsersController < ApplicationController
(...)
 def index
    @users = User.all
    @carousel =  YAML.load_file(Rails.root + 'config/carousel.yml')
  end
Enter fullscreen mode Exit fullscreen mode

Its very simple: We define the @users the usual way and read the complete yaml-file into @carousel.

Display carousel in the viewfile

The view-file is evenly simple

# app/views/users/index.html.erb
<header> {some stuff for the header section} </header>
<%= carousel "testCarousel", @carousel %>

....
Enter fullscreen mode Exit fullscreen mode

The hole code is delegated to the carousel-helper.

The code: Carousel-Helper

Essentially the Tailwind Elements -code is translated to fit into Rails-content_tag elements.

# /app/helpers/users_helper.rb

module UsersHelper

  def carusel id,  content
    slides =  content.count

    note = ->(n){ "<h2 class=\"text-4xl\">#{n[:title]}</h2> <p class=\"text-xl\">#{n[:text]}</p> "}

    content_tag( :div, class:  %w( carousel slide carousel-fade carousel-dark  relative ), :"data-bs-ride" => 'carousel', id: id ) do
      content_tag( :div , class: %w( carousel-indicators absolute right-0 bottom-0 left-0 flex justify-center p-0 mb-4 ) ) do
      raw( (0 .. slides).map do | count |
          label =  "Slide #{count + 1}"
          raw(  if count.zero?
           content_tag( :button , nil,  type: 'button', :"data-bs-target" => "##{id}" , :"data-bs-slide-to" => count, :"aria-current" => "true", :"aria-label" => label, class: "active" )
                else
           content_tag( :button , nil,  type: 'button', :"data-bs-target" => "##{id}" , :"data-bs-slide-to" => count, :"aria-label" => label )
                end
             )
        end.join)
      end +
       content_tag( :div, class: %w( carousel-inner relative w-3/2 overflow-hidden ) ) do
        raw( content.map.with_index do | c,index |
          h  = c.values.first
            # first image ist active
            class_attributes = index.zero? ? %w( carousel-item active relative float-left w-full ) : %w( carousel-item relative float-left w-full)
            content_tag( :div, class: class_attributes ) do
              content_tag( :a,  href: "##{h[:link]}" ) do 
              image_tag( h[:image]  , class: %w( block w-full)) +
              content_tag( :div , raw(note[h]), class: %w( carousel-caption hidden sm:block absolute text-center ) )
              end
            end
          end.join)
      end  +
      content_tag( :button, class: %w( carousel-control-prev absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline left-0 ),
                  type: 'button', :"data-bs-target" => "##{id}", :"data-bs-slide" => "prev") do
                      content_tag( :span, nil, class: %w( carousel-control-prev-icon inline-block bg-no-repeat ), :"aria-hidden" => "true") +
                      content_tag( :span, "Previous", class: "visually-hidden")
                                                                                            end +
      content_tag( :button, class: %w(carousel-control-next absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline right-0) ,
                  type: 'button', :"data-bs-target" => "##{id}", :"data-bs-slide"=> "next") do
                      content_tag( :span, nil, class: %w( carousel-control-next-icon inline-block bg-no-repeat ), :"aria-hidden" => "true") +
                      content_tag( :span, "Next", class: "visually-hidden")
                                                                                            end
    end


  end
end

Enter fullscreen mode Exit fullscreen mode

Et voila, the carousel is displayed in localhost:3000/users.

Further customization happens in the helper-code (by trained personal). The display-format for title and description, for example, can be changed in the Lambda in row 3.

Conclusion

The goal was, to separate Content and Function. Its just a matter of editing the `config/carousel.yml' file to update the contents of the carousel.

Top comments (0)