Class: UI::PopoverTriggerComponent

Inherits:
ViewComponent::Base
  • Object
show all
Includes:
PopoverTriggerBehavior
Defined in:
app/view_components/ui/popover_trigger_component.rb

Overview

TriggerComponent - ViewComponent implementation

Button or element that triggers the popover. Uses PopoverTriggerBehavior concern for shared styling logic.

Examples:

Basic usage

<%= render UI::TriggerComponent.new do %>
  <button>Click me</button>
<% end %>

As child (wraps content without adding wrapper)

<%= render UI::TriggerComponent.new(as_child: true) do %>
  <button>Click me</button>
<% end %>

Instance Method Summary collapse

Methods included from PopoverTriggerBehavior

#popover_trigger_classes, #popover_trigger_html_attributes

Constructor Details

#initialize(as_child: false, classes: "", **attributes) ⇒ PopoverTriggerComponent

Returns a new instance of PopoverTriggerComponent.

Parameters:

  • as_child (Boolean) (defaults to: false)

    If true, adds data attributes to child without wrapper

  • classes (String) (defaults to: "")

    Additional CSS classes to merge

  • attributes (Hash)

    Additional HTML attributes



23
24
25
26
27
# File 'app/view_components/ui/popover_trigger_component.rb', line 23

def initialize(as_child: false, classes: "", **attributes)
  @as_child = as_child
  @classes = classes
  @attributes = attributes
end

Instance Method Details

#callObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/view_components/ui/popover_trigger_component.rb', line 34

def call
  trigger_attrs = popover_trigger_html_attributes.deep_merge(@attributes)

  if @as_child
    # asChild mode: merge attributes into child element
    # Parse the rendered content and add trigger attributes to the first element
    rendered = content.to_s

    # Use Nokogiri to parse and modify the HTML
    doc = Nokogiri::HTML::DocumentFragment.parse(rendered)
    first_element = doc.children.find { |node| node.element? }

    if first_element
      # Merge data attributes
      trigger_attrs.fetch(:data, {}).each do |key, value|
        # Convert Rails naming convention to HTML: _ becomes -, __ becomes --
        html_key = key.to_s.gsub("__", "--").tr("_", "-")
        first_element["data-#{html_key}"] = value
      end

      # Merge CSS classes with TailwindMerge
      if trigger_attrs[:class]
        existing_classes = first_element["class"] || ""
        merged_classes = TailwindMerge::Merger.new.merge([existing_classes, trigger_attrs[:class]].join(" "))
        first_element["class"] = merged_classes
      end

      # Merge other attributes (except data and class)
      trigger_attrs.except(:data, :class).each do |key, value|
        first_element[key.to_s] = value
      end

      doc.to_html.html_safe
    else
      content
    end
  else
    # Default mode: render as div
     :div, **trigger_attrs do
      content
    end
  end
end

#trigger_attrsObject

Returns trigger attributes for as_child mode



30
31
32
# File 'app/view_components/ui/popover_trigger_component.rb', line 30

def trigger_attrs
  popover_trigger_html_attributes.deep_merge(@attributes)
end