ViewComponent for reusable UI components

Jordan Lee Jan 2026
3 tabs
class ButtonComponent < ViewComponent::Base
  VARIANTS = {
    primary: "bg-blue-600 hover:bg-blue-700 text-white",
    secondary: "bg-gray-200 hover:bg-gray-300 text-gray-900",
    danger: "bg-red-600 hover:bg-red-700 text-white"
  }.freeze

  SIZES = {
    sm: "px-3 py-1.5 text-sm",
    md: "px-4 py-2 text-base",
    lg: "px-6 py-3 text-lg"
  }.freeze

  def initialize(variant: :primary, size: :md, type: :button, **options)
    @variant = variant
    @size = size
    @type = type
    @options = options
  end

  def call
    content_tag :button, content, **html_options
  end

  private

  def html_options
    {
      type: @type,
      class: class_names
    }.merge(@options)
  end

  def class_names
    [
      "rounded font-medium transition-colors",
      VARIANTS[@variant],
      SIZES[@size],
      @options[:class]
    ].compact.join(" ")
  end
end
3 files · ruby, erb Explain with highlit

ViewComponents bring object-oriented design to Rails views, making complex UI elements testable and reusable. Each component is a Ruby class paired with a template, encapsulating both logic and presentation. I use components for buttons, cards, modals, form inputs—anything that appears multiple times with slight variations. Components accept parameters in their constructor, making them explicit about dependencies unlike partials that rely on instance variables. Testing is straightforward: instantiate the component, render it, and assert on the output. Components also integrate seamlessly with Stimulus controllers and can render slots for flexible composition. For design systems, components ensure consistency across the application.