1# frozen_string_literal: true 2 3module DropdownsHelper 4 def dropdown_tag(toggle_text, options: {}, &block) 5 content_tag :div, class: "dropdown #{options[:wrapper_class] if options.key?(:wrapper_class)}" do 6 data_attr = { toggle: "dropdown" } 7 8 if options.key?(:data) 9 data_attr = options[:data].merge(data_attr) 10 end 11 12 dropdown_output = dropdown_toggle(toggle_text, data_attr, options) 13 14 if options.key?(:toggle_link) 15 dropdown_output = dropdown_toggle_link(toggle_text, data_attr, options) 16 end 17 18 content_tag_options = { class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}" } 19 content_tag_options[:data] = { qa_selector: "#{options[:dropdown_qa_selector]}" } if options[:dropdown_qa_selector] 20 21 dropdown_output << content_tag(:div, content_tag_options) do 22 output = [] 23 24 if options.key?(:title) 25 output << dropdown_title(options[:title]) 26 end 27 28 if options.key?(:filter) 29 output << dropdown_filter(options[:placeholder]) 30 end 31 32 output << content_tag(:div, data: { qa_selector: "dropdown_list_content" }, class: "dropdown-content #{options[:content_class] if options.key?(:content_class)}") do 33 capture(&block) if block && !options.key?(:footer_content) 34 end 35 36 if block && options[:footer_content] 37 output << content_tag(:div, class: "dropdown-footer") do 38 capture(&block) 39 end 40 end 41 42 output << dropdown_loading 43 output.join.html_safe 44 end 45 46 dropdown_output.html_safe 47 end 48 end 49 50 def dropdown_toggle(toggle_text, data_attr, options = {}) 51 default_label = data_attr[:default_label] 52 content_tag(:button, disabled: options[:disabled], class: "dropdown-menu-toggle #{options[:toggle_class] if options.key?(:toggle_class)}", id: (options[:id] if options.key?(:id)), type: "button", data: data_attr) do 53 output = content_tag(:span, toggle_text, class: "dropdown-toggle-text #{'is-default' if toggle_text == default_label}") 54 output << sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3") 55 output.html_safe 56 end 57 end 58 59 def dropdown_toggle_link(toggle_text, data_attr, options = {}) 60 output = content_tag(:a, toggle_text, class: "dropdown-toggle-text #{options[:toggle_class] if options.key?(:toggle_class)}", id: (options[:id] if options.key?(:id)), data: data_attr) 61 output.html_safe 62 end 63 64 def dropdown_title(title, options: {}) 65 has_back = options.fetch(:back, false) 66 has_close = options.fetch(:close, true) 67 68 container_class = %w[dropdown-title gl-display-flex] 69 margin_class = [] 70 71 if has_back && has_close 72 container_class << 'gl-justify-content-space-between' 73 elsif has_back 74 margin_class << 'gl-mr-auto' 75 elsif has_close 76 margin_class << 'gl-ml-auto' 77 end 78 79 container_class = container_class.join(' ') 80 margin_class = margin_class.join(' ') 81 82 content_tag :div, class: container_class do 83 title_output = [] 84 85 if has_back 86 title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-back " + margin_class, aria: { label: "Go back" }, type: "button") do 87 sprite_icon('arrow-left') 88 end 89 end 90 91 title_output << content_tag(:span, title, class: margin_class) 92 93 if has_close 94 title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close " + margin_class, aria: { label: "Close" }, type: "button") do 95 sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon') 96 end 97 end 98 99 title_output.join.html_safe 100 end 101 end 102 103 def dropdown_filter(placeholder, search_id: nil) 104 content_tag :div, class: "dropdown-input" do 105 filter_output = search_field_tag search_id, nil, data: { qa_selector: "dropdown_input_field" }, id: nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off' 106 filter_output << sprite_icon('search', css_class: 'dropdown-input-search') 107 filter_output << sprite_icon('close', size: 16, css_class: 'dropdown-input-clear js-dropdown-input-clear') 108 109 filter_output.html_safe 110 end 111 end 112 113 def dropdown_content(&block) 114 content_tag(:div, class: "dropdown-content") do 115 if block 116 capture(&block) 117 end 118 end 119 end 120 121 def dropdown_footer(add_content_class: false, &block) 122 content_tag(:div, class: "dropdown-footer") do 123 if add_content_class 124 content_tag(:div, capture(&block), class: "dropdown-footer-content") 125 else 126 capture(&block) 127 end 128 end 129 end 130 131 def dropdown_loading 132 spinner = loading_icon(container: true, size: "md", css_class: "gl-mt-7") 133 content_tag(:div, spinner, class: "dropdown-loading") 134 end 135end 136