DEV Community

Rails Designer
Rails Designer

Posted on • Originally published at railsdesigner.com

2

Multiple component variants with Tailwind

This article was originally published on Rails Designer


One thing vanilla CSS does really well is extensibility. A good, and common, example of this is a button. With plain CSS you can build a base btn class and then a modifier btn-primary (or btn--primary to be BEM-like).

With Tailwind this is less easy to do, unless you use some sort of component system, like ViewComponent. Let's build just that today, so in your app you can write render ButtonComponent.new.with_content "Save" or render ButtonComponent.new(variant: "danger").with_content "Delete". No dependencies needed, only what Rails gives you.

Let's set up the basics:

class ButtonComponent < ApplicationComponent
  def initialize(variant: "primary")
    @variant = variant
  end

  def call
    tag.button content, class: classes
  end

  private

  def classes
    "inline-flex items-center px-3 py-2 text-sm font-medium text-white bg-blue-500 rounded-sm"
  end
end
Enter fullscreen mode Exit fullscreen mode

That's your typical button component. Let's make use of the @variant variable now.

class ButtonComponent < ApplicationComponent
  def initialize(variant: "primary")
    @variant = variant.inquiry
  end

  # …

private

  def classes
    class_names(
      "inline-flex items-center px-3 py-2 text-sm font-medium rounded-sm",
      {
        "text-white bg-blue-500": @variant.primary?
      }
    )
  end
end
Enter fullscreen mode Exit fullscreen mode

First inquiry is called on the @variant variable. I've written this article on inquiry, so be sure to check it out for all the details. Than in the classes method, I am using class_names. For the class_names helper I've also written a separate article.

The classes method is where everything comes together. You can see how clean having multiple variants is when the list is extended:

  def classes
    class_names(
      "inline-flex items-center px-3 py-2 text-sm font-medium rounded-sm",
      {
        "text-white bg-blue-500": @variant.primary?,
        "text-white bg-gray-600": @variant.secondary?,
        "text-white bg-green-600": @variant.success?,
        "text-white bg-red-600": @variant.danger?,
        "text-yellow-950 bg-yellow-500": @variant.warning?,
        "text-white bg-cyan-500": @variant.info?,
        "text-gray-900 bg-gray-50": @variant.light?,
        "text-white bg-gray-900": @variant.dark?,
        "text-blue-500 bg-transparent": @variant.text?
      }
    )
  end
Enter fullscreen mode Exit fullscreen mode

This is how they all look:

Image description

Next steps

If you want to use this component in your app, there are a few things you might want to add like:

  • a type variable, so you can use this a submit-button in forms;
  • any other options, eg. @options = options, then using the double-splat (**options) when passing it to the button element.

Simple and easy, right?

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Hot sauce if you're wrong - web dev trivia for staff engineers

Hot sauce if you're wrong · web dev trivia for staff engineers (Chris vs Jeremy, Leet Heat S1.E4)

  • Shipping Fast: Test your knowledge of deployment strategies and techniques
  • Authentication: Prove you know your OAuth from your JWT
  • CSS: Demonstrate your styling expertise under pressure
  • Acronyms: Decode the alphabet soup of web development
  • Accessibility: Show your commitment to building for everyone

Contestants must answer rapid-fire questions across the full stack of modern web development. Get it right, earn points. Get it wrong? The spice level goes up!

Watch Video 🌶️🔥

👋 Kindness is contagious

If you found this post helpful, please leave a ❤️ or a friendly comment below!

Okay