summaryrefslogtreecommitdiff
path: root/app/components/pajamas/button_component.rb
blob: b2dd798b718a39aaf45d7972140b2d3fe5710e0b (plain)
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
# frozen_string_literal: true

module Pajamas
  class ButtonComponent < Pajamas::Component
    # @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 [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,
      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
      @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

    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

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

    def link?
      @href.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
    end
  end
end