Module: UI::AccordionTriggerBehavior

Included in:
AccordionTrigger, AccordionTriggerComponent
Defined in:
app/behaviors/ui/accordion_trigger_behavior.rb

Overview

Shared behavior for Accordion Trigger (button) component Handles classes, ARIA attributes, and unique IDs

Instance Method Summary collapse

Instance Method Details

#aria_expandedObject

Determine aria-expanded value



38
39
40
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 38

def aria_expanded
  @initial_open ? "true" : "false"
end

#caret_svgObject

SVG caret icon (rotation handled by Tailwind’s [&[data-state=open]>svg] variant)



72
73
74
75
76
77
78
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 72

def caret_svg
  <<~SVG.html_safe
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-[var(--duration-accordion)]">
      <polyline points="6 9 12 15 18 9"></polyline>
    </svg>
  SVG
end

#content_idObject



23
24
25
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 23

def content_id
  @content_id ||= "accordion-content-#{item_value}"
end

#item_valueObject

Get item value from context (set by parent AccordionItem)



28
29
30
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 28

def item_value
  @item_value || SecureRandom.hex(4)
end

#merged_trigger_data_attributesObject

Merge user-provided data attributes



51
52
53
54
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 51

def merged_trigger_data_attributes
  user_data = @attributes&.fetch(:data, {}) || {}
  user_data.merge(trigger_data_attributes)
end

#trigger_base_classesObject

Base CSS classes for trigger button



9
10
11
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 9

def trigger_base_classes
  "flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:underline [&[data-state=open]>svg]:rotate-180"
end

#trigger_classesObject

Merge base classes with custom classes using TailwindMerge



14
15
16
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 14

def trigger_classes
  TailwindMerge::Merger.new.merge([trigger_base_classes, @classes].compact.join(" "))
end

#trigger_data_attributesObject

Data attributes for Stimulus



43
44
45
46
47
48
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 43

def trigger_data_attributes
  {
    ui__accordion_target: "trigger",
    action: "click->ui--accordion#toggle"
  }
end

#trigger_html_attributesObject

Build complete HTML attributes hash for trigger button



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 57

def trigger_html_attributes
  base_attrs = @attributes&.except(:data) || {}
  base_attrs.merge(
    class: trigger_classes,
    type: "button",
    id: trigger_id,
    "aria-expanded": aria_expanded,
    "aria-controls": content_id,
    "data-state": trigger_state,
    "data-orientation": @orientation || "vertical",
    data: merged_trigger_data_attributes
  )
end

#trigger_idObject

Generate unique IDs for ARIA relationships



19
20
21
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 19

def trigger_id
  @trigger_id ||= "accordion-trigger-#{item_value}"
end

#trigger_stateObject

Determine initial state from context



33
34
35
# File 'app/behaviors/ui/accordion_trigger_behavior.rb', line 33

def trigger_state
  @initial_open ? "open" : "closed"
end