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)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.