bs5 0.0.16 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/bs5/accordion_component.html.erb +1 -1
  3. data/app/components/bs5/accordion_component.rb +7 -3
  4. data/app/components/bs5/alert_component.rb +5 -5
  5. data/app/components/bs5/badge_component.rb +6 -6
  6. data/app/components/bs5/breadcrumb_component.html.erb +1 -1
  7. data/app/components/bs5/breadcrumb_component.rb +6 -3
  8. data/app/components/bs5/button_group_component.html.erb +3 -0
  9. data/app/components/bs5/button_group_component.rb +49 -0
  10. data/app/components/bs5/button_tag_component.rb +8 -8
  11. data/app/components/bs5/button_to_component.rb +8 -8
  12. data/app/components/bs5/button_toolbar_component.html.erb +3 -0
  13. data/app/components/bs5/button_toolbar_component.rb +21 -0
  14. data/app/components/bs5/list_group_component.html.erb +2 -2
  15. data/app/components/bs5/list_group_component.rb +16 -9
  16. data/app/components/bs5/spinner_component.html.erb +5 -0
  17. data/app/components/bs5/spinner_component.rb +65 -0
  18. data/app/helpers/bs5/components_helper.rb +2 -1
  19. data/app/views/bs5/examples/accordion/default/snippet.html.erb +4 -4
  20. data/app/views/bs5/examples/accordion/flush/snippet.html.erb +4 -4
  21. data/app/views/bs5/examples/alert/additional_content/snippet.html.erb +1 -1
  22. data/app/views/bs5/examples/alert/color/_example.html.erb +1 -0
  23. data/app/views/bs5/examples/alert/{style → color}/snippet.html.erb +8 -8
  24. data/app/views/bs5/examples/alert/dismissable/snippet.html.erb +1 -1
  25. data/app/views/bs5/examples/badge/color/_example.html.erb +2 -0
  26. data/app/views/bs5/examples/badge/color/snippet.html.erb +8 -0
  27. data/app/views/bs5/examples/badge/default/_example.html.erb +2 -1
  28. data/app/views/bs5/examples/badge/default/button.html.erb +3 -0
  29. data/app/views/bs5/examples/badge/pill/snippet.html.erb +8 -8
  30. data/app/views/bs5/examples/breadcrumb/default/snippet.html.erb +9 -9
  31. data/app/views/bs5/examples/button_group/button_toolbar/_example.html.erb +3 -0
  32. data/app/views/bs5/examples/button_group/button_toolbar/snippet.html.erb +18 -0
  33. data/app/views/bs5/examples/button_group/button_toolbar/snippet2.html.erb +27 -0
  34. data/app/views/bs5/examples/button_group/default/_example.html.erb +2 -0
  35. data/app/views/bs5/examples/button_group/default/snippet.html.erb +5 -0
  36. data/app/views/bs5/examples/button_group/sizing/_example.html.erb +2 -0
  37. data/app/views/bs5/examples/button_group/sizing/snippet.html.erb +17 -0
  38. data/app/views/bs5/examples/button_group/vertical/_example.html.erb +2 -0
  39. data/app/views/bs5/examples/button_group/vertical/snippet.html.erb +8 -0
  40. data/app/views/bs5/examples/buttons/button_tag/outline/snippet.html.erb +9 -9
  41. data/app/views/bs5/examples/buttons/button_tag/size/large.html.erb +2 -2
  42. data/app/views/bs5/examples/buttons/button_tag/size/small.html.erb +2 -2
  43. data/app/views/bs5/examples/buttons/button_tag/style/snippet.html.erb +9 -9
  44. data/app/views/bs5/examples/buttons/button_to/default/snippet.html.erb +3 -3
  45. data/app/views/bs5/examples/list_group/actionable/button.html.erb +5 -5
  46. data/app/views/bs5/examples/list_group/actionable/snippet.html.erb +5 -5
  47. data/app/views/bs5/examples/list_group/active/snippet.html.erb +5 -5
  48. data/app/views/bs5/examples/list_group/checkboxes_and_radios/default.html.erb +5 -5
  49. data/app/views/bs5/examples/list_group/checkboxes_and_radios/with_labels.html.erb +5 -5
  50. data/app/views/bs5/examples/list_group/custom_content/default.html.erb +3 -3
  51. data/app/views/bs5/examples/list_group/default/snippet.html.erb +5 -5
  52. data/app/views/bs5/examples/list_group/disabled/snippet.html.erb +5 -5
  53. data/app/views/bs5/examples/list_group/flush/snippet.html.erb +5 -5
  54. data/app/views/bs5/examples/list_group/horizontal/snippet.html.erb +18 -18
  55. data/app/views/bs5/examples/list_group/style/actionable.html.erb +9 -9
  56. data/app/views/bs5/examples/list_group/style/default.html.erb +9 -9
  57. data/app/views/bs5/examples/list_group/with_badges/default.html.erb +6 -6
  58. data/app/views/bs5/examples/popovers/default/snippet.html.erb +1 -1
  59. data/app/views/bs5/examples/popovers/four_directions/snippet.html.erb +4 -4
  60. data/app/views/bs5/examples/spinners/border/_example.html.erb +2 -0
  61. data/app/views/bs5/examples/spinners/border/snippet.html.erb +1 -0
  62. data/app/views/bs5/examples/spinners/buttons/_example.html.erb +2 -0
  63. data/app/views/bs5/examples/spinners/buttons/snippet.html.erb +15 -0
  64. data/app/views/bs5/examples/spinners/colors/_example.html.erb +2 -0
  65. data/app/views/bs5/examples/spinners/colors/snippet.html.erb +16 -0
  66. data/app/views/bs5/examples/spinners/growing/_example.html.erb +3 -0
  67. data/app/views/bs5/examples/spinners/growing/colors.html.erb +16 -0
  68. data/app/views/bs5/examples/spinners/growing/snippet.html.erb +1 -0
  69. data/app/views/bs5/examples/spinners/options/_example.html.erb +10 -0
  70. data/app/views/bs5/examples/spinners/options/floats.html.erb +3 -0
  71. data/app/views/bs5/examples/spinners/options/margin.html.erb +1 -0
  72. data/app/views/bs5/examples/spinners/options/placement_flex1.html.erb +3 -0
  73. data/app/views/bs5/examples/spinners/options/placement_flex2.html.erb +4 -0
  74. data/app/views/bs5/examples/spinners/options/text_align.html.erb +3 -0
  75. data/app/views/bs5/examples/spinners/size/_example.html.erb +3 -0
  76. data/app/views/bs5/examples/spinners/size/size1.html.erb +7 -0
  77. data/app/views/bs5/examples/spinners/size/size2.html.erb +3 -0
  78. data/app/views/bs5/examples/tooltips/default/buttons.html.erb +5 -5
  79. data/app/views/bs5/pages/alert.html.erb +1 -1
  80. data/app/views/bs5/pages/badge.html.erb +1 -1
  81. data/app/views/bs5/pages/button_group.html.erb +5 -0
  82. data/app/views/bs5/pages/popovers.html.erb +3 -0
  83. data/app/views/bs5/pages/spinners.html.erb +7 -0
  84. data/app/views/layouts/bs5/pages.html.erb +12 -10
  85. data/lib/bs5/version.rb +1 -1
  86. data/lib/tasks/rubocop.rake +2 -0
  87. metadata +55 -19
  88. data/app/views/bs5/examples/alert/style/_example.html.erb +0 -2
  89. data/app/views/bs5/examples/badge/style/_example.html.erb +0 -2
  90. data/app/views/bs5/examples/badge/style/snippet.html.erb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba1fb14f4e08a3c9b6e8196fd306954c3e2bbe5e7f074ff018dbcf5adb9554cb
4
- data.tar.gz: c7d797b046934929781283e825fcb74b3e9780faf544ce92dd2ca1b38cfbc60f
3
+ metadata.gz: ec13b3d4b022a8136ed67a797111aa537f4ba05a6dbf30ad9b8e8eb9099577e3
4
+ data.tar.gz: 0ac4e60fc0ad95d59e567133fd7dc5bb2d67555a0e97b7b2ceddc7e8b5ec0bd9
5
5
  SHA512:
6
- metadata.gz: f11d2a95bc6dcfe8539feeb6eba85eaa873096c0cf725aa4d800b72f86e29c39817ae867739422f549f0c3a6be0b1f378de57e8d2e03ae62daa5d4594de6ee64
7
- data.tar.gz: 1de41edf38036562b6fde14f20242926d557344875a4efdfc5a552d9a8cf7d2cc5d68fbe9cd2d815178fb2ae75f57a13be92aaf72fd9c19416ba8ee214967a4a
6
+ metadata.gz: 942a8e42a2cbaf93928690249f8ab1f9e914a3e9265529e3aff0d76d8bb739218dbeac3d420bbd1f0b154933d182d5a0433dc3fb031f82c496f683b4484856d8
7
+ data.tar.gz: 3e0c2dfd11427835d34de52ec59fded37e0904ce509ad7abec7595676871526c76c79ede5bfcda74a6e47890d85293c85c89bb575191e1041c50bed4af5e2c93
@@ -17,7 +17,7 @@
17
17
  data-bs-parent="#<%= id %>"
18
18
  >
19
19
  <div class="accordion-body">
20
- <%= item.content %>
20
+ <%= item %>
21
21
  </div>
22
22
  </div>
23
23
  </div>
@@ -3,9 +3,9 @@
3
3
  module Bs5
4
4
  class AccordionComponent < ViewComponent::Base
5
5
  include ComponentsHelper
6
- include ViewComponent::Slotable
6
+ include ViewComponent::SlotableV2
7
7
 
8
- with_slot :item, collection: true, class_name: 'Item'
8
+ renders_many :items, 'ItemComponent'
9
9
 
10
10
  def initialize(flush: false)
11
11
  @flush = flush
@@ -25,7 +25,7 @@ module Bs5
25
25
  class_names.join(' ')
26
26
  end
27
27
 
28
- class Item < ViewComponent::Slot
28
+ class ItemComponent < ViewComponent::Base
29
29
  attr_reader :title
30
30
 
31
31
  def initialize(title:, collapsed: true)
@@ -33,6 +33,10 @@ module Bs5
33
33
  @collapsed = collapsed
34
34
  end
35
35
 
36
+ def call
37
+ content
38
+ end
39
+
36
40
  def id
37
41
  object_id
38
42
  end
@@ -4,13 +4,13 @@ module Bs5
4
4
  class AlertComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark].freeze
6
6
 
7
- attr_reader :style, :is_dismissable
7
+ attr_reader :color, :is_dismissable
8
8
 
9
9
  include ActiveModel::Validations
10
- validates :style, style: true
10
+ validates :color, style: true
11
11
 
12
- def initialize(style: :primary, is_dismissable: false)
13
- @style = style.to_sym
12
+ def initialize(color: :primary, is_dismissable: false)
13
+ @color = color.to_sym
14
14
  @is_dismissable = is_dismissable
15
15
  end
16
16
 
@@ -31,7 +31,7 @@ module Bs5
31
31
  end
32
32
 
33
33
  def contextual_class
34
- "alert-#{@style}"
34
+ "alert-#{@color}"
35
35
  end
36
36
  end
37
37
  end
@@ -4,14 +4,14 @@ module Bs5
4
4
  class BadgeComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark].freeze
6
6
 
7
- attr_reader :text, :style
7
+ attr_reader :text, :color
8
8
 
9
9
  include ActiveModel::Validations
10
- validates :style, style: true
10
+ validates :color, style: true
11
11
 
12
- def initialize(text:, style: :secondary, pill: false)
12
+ def initialize(text:, color: :secondary, pill: false)
13
13
  @text = text
14
- @style = style.to_sym
14
+ @color = color.to_sym
15
15
  @pill = pill
16
16
  end
17
17
 
@@ -32,8 +32,8 @@ module Bs5
32
32
  end
33
33
 
34
34
  def contextual_class
35
- class_names = ["bg-#{@style}"]
36
- class_names << %w[text-dark] if style.in?(%i[warning info light])
35
+ class_names = ["bg-#{@color}"]
36
+ class_names << %w[text-dark] if color.in?(%i[warning info light])
37
37
  class_names.join(' ')
38
38
  end
39
39
  end
@@ -2,7 +2,7 @@
2
2
  <nav aria-label="breadcrumb">
3
3
  <ol class="breadcrumb">
4
4
  <% items.each do |item| %>
5
- <li class="breadcrumb-item <%= item == items.last ? 'active' : '' %>" <%= item == items.last ? 'aria-current=page' : '' %>><%= item.content %></li>
5
+ <li class="breadcrumb-item <%= item == items.last ? 'active' : '' %>" <%= item == items.last ? 'aria-current=page' : '' %>><%= item %></li>
6
6
  <% end %>
7
7
  </ol>
8
8
  </nav>
@@ -2,11 +2,14 @@
2
2
 
3
3
  module Bs5
4
4
  class BreadcrumbComponent < ViewComponent::Base
5
- include ViewComponent::Slotable
5
+ include ViewComponent::SlotableV2
6
6
 
7
- with_slot :item, collection: true, class_name: 'Item'
7
+ renders_many :items, 'ItemComponent'
8
8
 
9
- class Item < ViewComponent::Slot
9
+ class ItemComponent < ViewComponent::Base
10
+ def call
11
+ content
12
+ end
10
13
  end
11
14
  end
12
15
  end
@@ -0,0 +1,3 @@
1
+ <%= tag.div(component_attributes) do %>
2
+ <%= content %>
3
+ <% end %>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class ButtonGroupComponent < ViewComponent::Base
5
+ SIZES = { small: :sm, large: :lg }.with_indifferent_access.freeze
6
+ CLASS_PREFIX = 'btn-group'
7
+
8
+ attr_reader :vertical, :size
9
+
10
+ def initialize(options = {})
11
+ @options = options.symbolize_keys
12
+ @vertical = @options.delete(:vertical)
13
+ @size = @options.delete(:size)
14
+ end
15
+
16
+ def render?
17
+ content.present?
18
+ end
19
+
20
+ def component_attributes
21
+ default_options = { role: 'group' }
22
+ @options[:class] = component_class
23
+ @options.merge(default_options)
24
+ end
25
+
26
+ private
27
+
28
+ def component_class
29
+ class_names = Array(@options[:class])
30
+ class_names << vertical_class
31
+ class_names << size_class
32
+ class_names
33
+ end
34
+
35
+ def vertical_class
36
+ @vertical ? "#{CLASS_PREFIX}-vertical" : CLASS_PREFIX
37
+ end
38
+
39
+ def size_class
40
+ return unless size?
41
+
42
+ [CLASS_PREFIX, SIZES[size]].join('-')
43
+ end
44
+
45
+ def size?
46
+ !!size
47
+ end
48
+ end
49
+ end
@@ -3,14 +3,14 @@
3
3
  module Bs5
4
4
  class ButtonTagComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark link].freeze
6
- DEFAULT_STYLE = :primary
6
+ DEFAULT_COLOR = :primary
7
7
  SIZES = { small: :sm, large: :lg }.freeze
8
8
  CLASS_PREFIX = 'btn'
9
9
 
10
10
  attr_reader :content_or_options, :size
11
11
 
12
12
  include ActiveModel::Validations
13
- validates :style, style: true
13
+ validates :color, style: true
14
14
  validates :size, inclusion: { in: SIZES.keys, valid_sizes: SIZES.keys.to_sentence, allow_nil: true }
15
15
 
16
16
  def initialize(content_or_options = nil, options = nil)
@@ -44,13 +44,13 @@ module Bs5
44
44
  end
45
45
 
46
46
  def extract_custom_options
47
- extract_style
47
+ extract_color
48
48
  extract_outline
49
49
  extract_size
50
50
  end
51
51
 
52
- def extract_style
53
- @style = @options.delete(:style)
52
+ def extract_color
53
+ @color = @options.delete(:color)
54
54
  end
55
55
 
56
56
  def extract_outline
@@ -76,7 +76,7 @@ module Bs5
76
76
  end
77
77
 
78
78
  def contextual_class
79
- [CLASS_PREFIX, outline? ? 'outline' : nil, style].compact.join('-')
79
+ [CLASS_PREFIX, outline? ? 'outline' : nil, color].compact.join('-')
80
80
  end
81
81
 
82
82
  def size_class
@@ -85,8 +85,8 @@ module Bs5
85
85
  [CLASS_PREFIX, SIZES[size]].join('-')
86
86
  end
87
87
 
88
- def style
89
- (@style || DEFAULT_STYLE).to_sym
88
+ def color
89
+ (@color || DEFAULT_COLOR).to_sym
90
90
  end
91
91
 
92
92
  def outline?
@@ -3,14 +3,14 @@
3
3
  module Bs5
4
4
  class ButtonToComponent < ViewComponent::Base
5
5
  STYLES = %i[primary secondary success danger warning info light dark link].freeze
6
- DEFAULT_STYLE = :primary
6
+ DEFAULT_COLOR = :primary
7
7
  SIZES = { small: :sm, large: :lg }.freeze
8
8
  CLASS_PREFIX = 'btn'
9
9
 
10
10
  attr_reader :size
11
11
 
12
12
  include ActiveModel::Validations
13
- validates :style, style: true
13
+ validates :color, style: true
14
14
  validates :size, inclusion: { in: SIZES.keys, valid_sizes: SIZES.keys.to_sentence, allow_nil: true }
15
15
 
16
16
  def initialize(name = nil, options = nil, html_options = nil)
@@ -53,13 +53,13 @@ module Bs5
53
53
  end
54
54
 
55
55
  def extract_custom_options
56
- extract_style
56
+ extract_color
57
57
  extract_outline
58
58
  extract_size
59
59
  end
60
60
 
61
- def extract_style
62
- @style = @button_to_options.delete(:style)
61
+ def extract_color
62
+ @color = @button_to_options.delete(:color)
63
63
  end
64
64
 
65
65
  def extract_outline
@@ -85,7 +85,7 @@ module Bs5
85
85
  end
86
86
 
87
87
  def contextual_class
88
- [CLASS_PREFIX, outline? ? 'outline' : nil, style].compact.join('-')
88
+ [CLASS_PREFIX, outline? ? 'outline' : nil, color].compact.join('-')
89
89
  end
90
90
 
91
91
  def size_class
@@ -94,8 +94,8 @@ module Bs5
94
94
  [CLASS_PREFIX, SIZES[size]].join('-')
95
95
  end
96
96
 
97
- def style
98
- (@style || DEFAULT_STYLE).to_sym
97
+ def color
98
+ (@color || DEFAULT_COLOR).to_sym
99
99
  end
100
100
 
101
101
  def outline?
@@ -0,0 +1,3 @@
1
+ <%= tag.div(component_attributes) do %>
2
+ <%= content %>
3
+ <% end %>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class ButtonToolbarComponent < ViewComponent::Base
5
+ def initialize(options = {})
6
+ @options = options
7
+ end
8
+
9
+ def render?
10
+ content.present?
11
+ end
12
+
13
+ def component_attributes
14
+ default_options = { role: 'toolbar' }
15
+ @options[:class] = Array(@options[:class])
16
+ @options[:class] << 'btn-toolbar'
17
+
18
+ @options.merge(default_options)
19
+ end
20
+ end
21
+ end
@@ -2,14 +2,14 @@
2
2
  <% if actionables? %>
3
3
  <div class="<%= component_class %>">
4
4
  <% items.each do |item| %>
5
- <%= item.decorated_content %>
5
+ <%= item %>
6
6
  <% end %>
7
7
  </div>
8
8
  <% else %>
9
9
  <ul class="<%= component_class %>">
10
10
  <% items.each do |item| %>
11
11
  <%= tag.li(**item.options) do %>
12
- <%= item.content %>
12
+ <%= item %>
13
13
  <% end %>
14
14
  <% end %>
15
15
  </ul>
@@ -6,9 +6,9 @@ module Bs5
6
6
  CLASS_NAME_FLUSH = "#{CLASS_NAME_BASE}-flush"
7
7
  CLASS_NAME_HORIZONTAL = "#{CLASS_NAME_BASE}-horizontal"
8
8
 
9
- include ViewComponent::Slotable
9
+ include ViewComponent::SlotableV2
10
10
 
11
- with_slot :item, collection: true, class_name: 'Item'
11
+ renders_many :items, 'Item'
12
12
 
13
13
  def initialize(flush: false, horizontal: false)
14
14
  @flush = flush
@@ -22,7 +22,10 @@ module Bs5
22
22
  end
23
23
 
24
24
  def actionables?
25
- items.any?(&:actionable?)
25
+ items.any? do |item|
26
+ elements = Nokogiri::HTML::DocumentFragment.parse(item.to_s).elements
27
+ elements.one? && elements.first.name.in?(%w[a button label])
28
+ end
26
29
  end
27
30
 
28
31
  def horizontal?
@@ -48,7 +51,7 @@ module Bs5
48
51
  class_names.join('-')
49
52
  end
50
53
 
51
- class Item < ViewComponent::Slot
54
+ class Item < ViewComponent::Base
52
55
  CLASS_NAME_BASE = 'list-group-item'
53
56
  CLASS_NAME_ACTION = "#{CLASS_NAME_BASE}-action"
54
57
 
@@ -59,11 +62,15 @@ module Bs5
59
62
 
60
63
  @active = @options.delete(:active) || false
61
64
  @disabled = @options.delete(:disabled) || false
62
- @style = @options.delete(:style)
65
+ @color = @options.delete(:color)
63
66
 
64
67
  set_attributes
65
68
  end
66
69
 
70
+ def call
71
+ actionable? ? decorated_content : content
72
+ end
73
+
67
74
  def actionable?
68
75
  !!actionable_element
69
76
  end
@@ -118,7 +125,7 @@ module Bs5
118
125
  class_names = [CLASS_NAME_BASE]
119
126
  class_names << 'active' if active?
120
127
  class_names << 'disabled' if disabled?
121
- class_names << contextual_class if style?
128
+ class_names << contextual_class if color?
122
129
 
123
130
  class_names
124
131
  end
@@ -131,12 +138,12 @@ module Bs5
131
138
  !!@disabled
132
139
  end
133
140
 
134
- def style?
135
- !!@style
141
+ def color?
142
+ !!@color
136
143
  end
137
144
 
138
145
  def contextual_class
139
- [CLASS_NAME_BASE, @style].join('-')
146
+ [CLASS_NAME_BASE, @color].join('-')
140
147
  end
141
148
  end
142
149
  end
@@ -0,0 +1,5 @@
1
+ <%= tag.div(**component_attributes) do %>
2
+ <%- if text %>
3
+ <span class="visually-hidden"><%= text %></span>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ class SpinnerComponent < ViewComponent::Base
5
+ STYLES = %i[primary secondary success danger warning info light dark].freeze
6
+ SIZES = { small: :sm, large: :lg }.freeze
7
+
8
+ attr_reader :text, :color, :size, :options
9
+
10
+ include ActiveModel::Validations
11
+ validates :color, style: true, if: -> { color }
12
+
13
+ def initialize(options = {})
14
+ @options = options.symbolize_keys
15
+
16
+ @text = @options.delete(:text)
17
+ @color = @options.delete(:color)&.to_sym
18
+ @grow = @options.delete(:grow)
19
+ @size = @options.delete(:size)&.to_sym
20
+ end
21
+
22
+ def before_render
23
+ raise errors.full_messages.to_sentence if invalid?
24
+ end
25
+
26
+ def component_attributes
27
+ options[:class] = component_class
28
+ options[:role] = 'status'
29
+ options
30
+ end
31
+
32
+ def component_class
33
+ class_names = Array(options[:class])
34
+ class_names << shape_class
35
+ class_names << contextual_class
36
+ class_names << size_class
37
+
38
+ class_names.compact.join(' ')
39
+ end
40
+
41
+ private
42
+
43
+ def shape_class
44
+ grow? ? 'spinner-grow' : 'spinner-border'
45
+ end
46
+
47
+ def contextual_class
48
+ "text-#{@color}" if color
49
+ end
50
+
51
+ def size_class
52
+ return unless size?
53
+
54
+ [shape_class, SIZES[size]].join('-')
55
+ end
56
+
57
+ def grow?
58
+ !!@grow
59
+ end
60
+
61
+ def size?
62
+ !!size
63
+ end
64
+ end
65
+ end