File: button_component.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (140 lines) | stat: -rw-r--r-- 3,998 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

module Pajamas
  class ButtonComponent < Pajamas::Component
    CATEGORY_OPTIONS = [:primary, :secondary, :tertiary].freeze
    VARIANT_OPTIONS = [:default, :confirm, :danger, :dashed, :link, :reset].freeze
    SIZE_OPTIONS = [:small, :medium].freeze
    TYPE_OPTIONS = [:button, :reset, :submit].freeze
    TARGET_OPTIONS = %w[_self _blank _parent _top].freeze
    METHOD_OPTIONS = [:get, :post, :put, :delete, :patch].freeze

    CATEGORY_CLASSES = {
      primary: '',
      secondary: 'secondary',
      tertiary: 'tertiary'
    }.freeze

    VARIANT_CLASSES = {
      default: 'btn-default',
      confirm: 'btn-confirm',
      danger: 'btn-danger',
      dashed: 'btn-dashed',
      link: 'btn-link',
      reset: 'btn-gl-reset'
    }.freeze

    NON_CATEGORY_VARIANTS = [:dashed, :link, :reset].freeze

    SIZE_CLASSES = {
      small: 'btn-sm',
      medium: 'btn-md'
    }.freeze

    # Below slot must be used as an exception to render custom icon image that is available from assets,
    # configs, attachments, etc. For all other regular cases please use :icon param to add an icon.
    renders_one :icon_content

    # @param [Symbol] category
    # @param [Symbol] variant
    # @param [Symbol] size
    # @param [Symbol] type
    # @param [Boolean] disabled
    # @param [Boolean] loading
    # @param [Boolean] block
    # @param [Boolean] selected
    # @param [String] icon
    # @param [String] href
    # @param [Boolean] form
    # @param [String] target
    # @param [Symbol] method
    # @param [Hash] button_options
    # @param [String] button_text_classes
    # @param [String] icon_classes
    def initialize(
      category: :primary,
      variant: :default,
      size: :medium,
      type: :button,
      disabled: false,
      loading: false,
      block: false,
      selected: false,
      icon: nil,
      href: nil,
      form: false,
      target: nil,
      method: nil,
      button_options: {},
      button_text_classes: nil,
      icon_classes: nil
    )
      @category = filter_attribute(category.to_sym, CATEGORY_OPTIONS)
      @variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS)
      @size = filter_attribute(size.to_sym, SIZE_OPTIONS)
      @type = filter_attribute(type.to_sym, TYPE_OPTIONS, default: :button)
      @disabled = disabled
      @loading = loading
      @block = block
      @selected = selected
      @icon = icon
      @href = href
      @form = form
      @target = filter_attribute(target, TARGET_OPTIONS)
      @method = filter_attribute(method, METHOD_OPTIONS)
      @button_options = button_options
      @button_text_classes = button_text_classes
      @icon_classes = icon_classes
    end

    private

    def button_class
      classes = ['gl-button btn']
      classes.push('disabled') if @disabled || @loading
      classes.push('selected') if @selected
      classes.push('btn-block') if @block
      classes.push('btn-icon') if @icon && !content

      classes.push(SIZE_CLASSES[@size])

      classes.push(VARIANT_CLASSES[@variant])

      unless NON_CATEGORY_VARIANTS.include?(@variant) || @category == :primary
        classes.push("#{VARIANT_CLASSES[@variant]}-#{CATEGORY_CLASSES[@category]}")
      end

      classes.push(@button_options[:class])

      classes.join(' ')
    end

    delegate :sprite_icon, to: :helpers
    delegate :gl_loading_icon, to: :helpers

    def link?
      @href.present?
    end

    def form?
      @href.present? && @form.present?
    end

    def base_attributes
      attributes = {}

      attributes['disabled'] = 'disabled' if @disabled || @loading
      attributes['aria-disabled'] = true if @disabled || @loading
      attributes['type'] = @type unless @href
      attributes['rel'] = safe_rel_for_target_blank if link? && @target == '_blank'

      attributes
    end

    def safe_rel_for_target_blank
      (@button_options[:rel] || '').split(' ')
        .concat(%w[noopener noreferrer])
        .uniq.join(' ')
    end
  end
end