Skip to content

Support for global definitions #36

@javierav

Description

@javierav

The most basic way to work with class_variants in Rails is the one shown in the readme itself:

# Somewhere in your helpers
def button_classes
  class_variants(
    base: "inline-flex items-center rounded border border-transparent font-medium text-white hover:text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2",
    variants: {
      size: {
        sm: "px-2.5 py-1.5 text-xs",
        md: "px-3 py-2 text-sm",
        lg: "px-4 py-2 text-sm",
        xl: "px-4 py-2 text-base",
      },
      color: {
        indigo: "bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-500",
        red: "bg-red-600 hover:bg-red-700 focus:ring-red-500",
        blue: "bg-blue-600 hover:bg-blue-700 focus:ring-blue-500",
      },
    },
    defaults: {
      size: :md,
      color: :indigo,
    }
  )
end
<!-- In your views -->
<%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :blue, size: :sm) %>
<%= link_to :Avo, "https://avohq.io", class: button_classes.render %>
<%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :red, size: :xl) %>

But this means that every time button_classes is called on a view, a new instance of ClassVariants::Instance is created, identical to the previous one. This is far from optimal.

The same thing happens if we want to use it inside a rails helper:

module ButtonHelper
  def button(**options, &block)
    cv = class_variants(
      variants: { color: { red: "bg-red-500", green: "bg-green-500" } },
      defaults: { color: :red }
    )
    tag.button(class: cv.render(**options), **options, &block)
  end
end

To avoid this, I think it would be interesting to implement some way in the gem to define global variants that are only created when Rails is initialized (for example, in an initializer) and that can then be used in helpers without having to re-instantiate the definition. For example:

# config/initializers/class_variants.rb
ClassVariants.define :button do
  variant color: :red, class: "bg-red-500"
  variant color: :green, class: "bg-green-500"
  defaults color: :red
end

# app/helpers/button_helper.rb
module ButtonHelper
  def button(**options, &block)
    tag.button(class: ClassVariants.for(:button).render(**options), **options, &block)
  end
end

What do you think @adrianthedev?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions