bulma_x 0.2.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +22 -0
  4. data/CHANGELOG.md +30 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/LICENSE +661 -0
  7. data/README.md +315 -0
  8. data/Rakefile +12 -0
  9. data/lib/bulma_x/base_component.rb +125 -0
  10. data/lib/bulma_x/base_input.rb +37 -0
  11. data/lib/bulma_x/block.rb +7 -0
  12. data/lib/bulma_x/box.rb +7 -0
  13. data/lib/bulma_x/breadcrumbs.rb +35 -0
  14. data/lib/bulma_x/button.rb +42 -0
  15. data/lib/bulma_x/card.rb +55 -0
  16. data/lib/bulma_x/checkbox.rb +23 -0
  17. data/lib/bulma_x/columns.rb +81 -0
  18. data/lib/bulma_x/component_dsl.rb +19 -0
  19. data/lib/bulma_x/dropdown.rb +65 -0
  20. data/lib/bulma_x/dsl/options.rb +129 -0
  21. data/lib/bulma_x/dsl/slots.rb +234 -0
  22. data/lib/bulma_x/dsl/validations.rb +74 -0
  23. data/lib/bulma_x/field.rb +150 -0
  24. data/lib/bulma_x/figure.rb +27 -0
  25. data/lib/bulma_x/file.rb +54 -0
  26. data/lib/bulma_x/footer.rb +7 -0
  27. data/lib/bulma_x/form.rb +27 -0
  28. data/lib/bulma_x/grid.rb +90 -0
  29. data/lib/bulma_x/help.rb +7 -0
  30. data/lib/bulma_x/hero.rb +36 -0
  31. data/lib/bulma_x/icon.rb +66 -0
  32. data/lib/bulma_x/image.rb +42 -0
  33. data/lib/bulma_x/input.rb +53 -0
  34. data/lib/bulma_x/level.rb +43 -0
  35. data/lib/bulma_x/link.rb +44 -0
  36. data/lib/bulma_x/media.rb +19 -0
  37. data/lib/bulma_x/message.rb +27 -0
  38. data/lib/bulma_x/modal.rb +26 -0
  39. data/lib/bulma_x/navbar.rb +162 -0
  40. data/lib/bulma_x/notification.rb +15 -0
  41. data/lib/bulma_x/pagination.rb +86 -0
  42. data/lib/bulma_x/panel.rb +29 -0
  43. data/lib/bulma_x/paragraph.rb +7 -0
  44. data/lib/bulma_x/progress.rb +36 -0
  45. data/lib/bulma_x/radio.rb +33 -0
  46. data/lib/bulma_x/section.rb +35 -0
  47. data/lib/bulma_x/select.rb +57 -0
  48. data/lib/bulma_x/shared/aria_options.rb +19 -0
  49. data/lib/bulma_x/shared/data_options.rb +19 -0
  50. data/lib/bulma_x/shared/flex_options.rb +57 -0
  51. data/lib/bulma_x/shared/global_options.rb +49 -0
  52. data/lib/bulma_x/shared/spacing_options.rb +80 -0
  53. data/lib/bulma_x/shared/text_options.rb +31 -0
  54. data/lib/bulma_x/slot.rb +13 -0
  55. data/lib/bulma_x/subtitle.rb +9 -0
  56. data/lib/bulma_x/table.rb +78 -0
  57. data/lib/bulma_x/tabs.rb +43 -0
  58. data/lib/bulma_x/tag.rb +25 -0
  59. data/lib/bulma_x/textarea.rb +29 -0
  60. data/lib/bulma_x/title.rb +21 -0
  61. data/lib/bulma_x/version.rb +5 -0
  62. data/lib/bulma_x/vertical_menu.rb +71 -0
  63. data/lib/bulma_x.rb +9 -0
  64. metadata +123 -0
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Field < BaseComponent
5
+ option :size, values: %i[small medium large], default: :medium
6
+
7
+ option :has_addons, values: BOOLEAN, default: false
8
+ option :addons_alignment, values: %i[centered left right], default: :centered
9
+
10
+ option :grouped, values: BOOLEAN, default: false
11
+ option :group_alignment, values: %i[centered left right], default: :centered
12
+ option :group_multiline, values: BOOLEAN, default: false
13
+
14
+ option :expanded, values: BOOLEAN, default: false
15
+ option :narrow, values: BOOLEAN, default: false
16
+ option :horizontal, values: BOOLEAN, default: false
17
+
18
+ option :disabled, values: BOOLEAN, default: false
19
+
20
+ root_slot classes: ['field']
21
+
22
+ slot :label, component: 'Label'
23
+ slot :field_label, component: 'FieldLabel'
24
+ slots :control, component: 'Control'
25
+ slots :field, component: 'self'
26
+ slot :help, component: Help
27
+ slot :field_body, classes: ['field-body']
28
+
29
+ def view_template(&)
30
+ if @disabled
31
+ fieldset(disabled: true) { render_self(&) }
32
+ else
33
+ render_self(&)
34
+ end
35
+ end
36
+
37
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/CyclomaticComplexity
38
+ def render_self
39
+ render_root do
40
+ slot(:field_label) if slot?(:field_label)
41
+
42
+ if @horizontal || slot?(:field)
43
+ slot(:field_body) do
44
+ slots(:field).each { render it }
45
+ end
46
+ else
47
+ unless slot?(:field_label)
48
+ slot(:label) if slot?(:label)
49
+
50
+ slots(:control).each { render it }
51
+ end
52
+ end
53
+
54
+ slot(:help) if slot?(:help)
55
+ end
56
+ end
57
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/CyclomaticComplexity
58
+
59
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
60
+ def root_classes
61
+ super +
62
+ [
63
+ 'field',
64
+ @has_addons && 'has-addons',
65
+ @has_addons && @addons_alignment && "has-addons-#{@addons_alignment}",
66
+ @grouped && 'is-grouped',
67
+ @grouped && @group_alignment && "is-grouped-#{@group_alignment}",
68
+ @grouped && @group_multiline && 'is-grouped-multiline',
69
+ @expanded && 'is-expanded',
70
+ @narrow && 'is-narrow',
71
+ @horizontal && 'is-horizontal'
72
+ ]
73
+ end
74
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
75
+
76
+ class Control < BaseComponent
77
+ option :expanded, values: BOOLEAN, default: false
78
+
79
+ slots :label, component: 'BulmaX::Field::Label'
80
+ slot :input, component: Input
81
+ slot :textarea, component: Textarea
82
+ slot :select, component: Select
83
+ slot :button, component: Button
84
+ slot :left_icon, component: Icon
85
+ slot :right_icon, component: Icon
86
+
87
+ def root_classes
88
+ super +
89
+ [
90
+ 'control',
91
+ slot?(:left_icon) && 'has-icons-left',
92
+ slot?(:right_icon) && 'has-icons-right',
93
+ @expanded && 'is-expanded'
94
+ ]
95
+ end
96
+
97
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
98
+ def view_template(&)
99
+ super do
100
+ slot(:left_icon, control_alignment: :left) if slot?(:left_icon)
101
+ slots(:label).each { render it }
102
+ slot(:input) if slot?(:input)
103
+ slot(:textarea) if slot?(:textarea)
104
+ slot(:select) if slot?(:select)
105
+ slot(:button) if slot?(:button)
106
+ slot(:right_icon, control_alignment: :right) if slot?(:right_icon)
107
+ yield if block_given?
108
+ end
109
+ end
110
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
111
+ end
112
+
113
+ class Label < BaseComponent
114
+ option :size, values: %i[small normal medium large], default: 'medium'
115
+ option :input, values: Input.type_values
116
+
117
+ root_slot tag: :label
118
+
119
+ slot :input, component: Input
120
+
121
+ def root_classes
122
+ super +
123
+ [
124
+ @input || 'label', # if the label is specialized it should not be a .label
125
+ "is-#{@size}"
126
+ ]
127
+ end
128
+
129
+ def view_template(&)
130
+ super do
131
+ slot(:input) if slot?(:input)
132
+
133
+ yield self if block_given?
134
+ end
135
+ end
136
+ end
137
+
138
+ class FieldLabel < Label
139
+ slot :label, component: Label
140
+
141
+ def root_classes = super - ['label'] + ['field-label']
142
+
143
+ def view_template(&)
144
+ super do
145
+ slot(:label, &) if slot?(:label) || block_given?
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Figure < BaseComponent
5
+ RATIOS = %w[square 1x1 5x4 4x3 3x2 5x3 16x9 2x1 3x1 4x5 3x4 2x3 3x5 9x16 1x2 1x3].freeze
6
+
7
+ option :size, values: [16, 24, 32, 48, 64, 96, 128], default: nil
8
+ option :ratio, values: RATIOS + [nil]
9
+
10
+ root_slot tag: :figure
11
+
12
+ def root_classes
13
+ super +
14
+ [
15
+ 'image',
16
+ @size && "is-#{@size}x#{@size}",
17
+ @ratio && normalize_ratio(@ratio)
18
+ ]
19
+ end
20
+
21
+ def normalize_ratio(ratio)
22
+ return nil if ratio.nil?
23
+
24
+ "is-#{ratio.split('x').join('by')}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class File < BaseComponent
5
+ option :boxed, values: BOOLEAN, default: false
6
+ option :has_name, values: BOOLEAN, default: false
7
+ option :modifier, values: MODIFIERS, default: nil
8
+ option :size, values: %w[small normal medium large], default: 'normal'
9
+ option :icon, default: 'folder_open'
10
+ option :caption, default: 'Choose a file'
11
+
12
+ slot :label, tag: :label, classes: ['file-label']
13
+ slot :input, tag: :input, classes: ['file-input'], attributes: { type: 'file', name: 'resume' }
14
+ slot :icon, tag: :span, classes: ['file-icon']
15
+ slot :cta, tag: :span, classes: ['file-cta']
16
+ slot :cta_label, tag: :span, classes: ['file-label']
17
+ slot :name, tag: :span, classes: ['file-name']
18
+
19
+ def view_template
20
+ super do
21
+ slot(:label) do
22
+ slot(:input)
23
+
24
+ yield if block_given?
25
+
26
+ slot(:cta) do
27
+ slot(:icon)
28
+
29
+ slot(:cta_label) { plain @caption }
30
+ end
31
+
32
+ slot(:name) if @has_name # to be filled by JS
33
+ end
34
+ end
35
+ end
36
+
37
+ def root_classes
38
+ super +
39
+ [
40
+ 'file',
41
+ @boxed && 'is-boxed',
42
+ @modifier && "is-#{@modifier}",
43
+ "is-#{@size}"
44
+ ]
45
+ end
46
+
47
+ def file_input_classes
48
+ [
49
+ 'file-input',
50
+ @boxed && 'is-boxed'
51
+ ]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Footer < BaseComponent
5
+ root_slot tag: :footer, classes: ['footer']
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Form < BaseComponent
5
+ root_slot tag: :form
6
+
7
+ option :url
8
+ option :method, values: %i[get post put patch delete], default: :post
9
+ option :accept_charset, default: 'UTF-8'
10
+
11
+ slots :field, component: Field
12
+
13
+ def view_template
14
+ super do
15
+ slots(:field).each { render it }
16
+ end
17
+ end
18
+
19
+ def root_attributes
20
+ super.merge(
21
+ method: @method,
22
+ action: @url,
23
+ accept_charset: @accept_charset
24
+ )
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Grid < BaseComponent
5
+ option :size, values: (0..12).to_a.push(nil), default: nil
6
+ option :columns, values: (0..12).to_a.push(nil), default: nil
7
+ option :mobile_columns, values: (0..12).to_a.push(nil), default: nil
8
+ option :tablet_columns, values: (0..12).to_a.push(nil), default: nil
9
+ option :desktop_columns, values: (0..12).to_a.push(nil), default: nil
10
+ option :widescreen_columns, values: (0..12).to_a.push(nil), default: nil
11
+ option :fullhd_columns, values: (0..12).to_a.push(nil), default: nil
12
+
13
+ option :gap, values: (0..8).to_a.push(nil), default: nil
14
+ option :auto_count, values: BOOLEAN, default: false
15
+
16
+ slot :grid_container
17
+ slots :cell, component: 'Cell'
18
+
19
+ def view_template
20
+ if any_columns? || @auto_count
21
+ slot(:grid_container) do
22
+ render_self
23
+ end
24
+ else
25
+ render_self
26
+ end
27
+ end
28
+
29
+ def render_self
30
+ render_root do
31
+ slots(:cell).each { render it }
32
+ end
33
+ end
34
+
35
+ # rubocop:disable Metrics/CyclomaticComplexity
36
+ def grid_container_classes
37
+ [
38
+ 'fixed-grid',
39
+ @columns && "has-#{@columns}-cols",
40
+ @mobile_columns && "has-#{@mobile_columns}-cols-mobile",
41
+ @tablet_columns && "has-#{@tablet_columns}-cols-tablet",
42
+ @desktop_columns && "has-#{@desktop_columns}-cols-desktop",
43
+ @widescreen_columns && "has-#{@widescreen_columns}-cols-widescreen",
44
+ @fullhd_columns && "has-#{@fullhd_columns}-cols-fullhd",
45
+ @auto_count && 'has-auto-count'
46
+ ]
47
+ end
48
+ # rubocop:enable Metrics/CyclomaticComplexity
49
+
50
+ def root_classes
51
+ super +
52
+ [
53
+ 'grid',
54
+ @size && "is-col-min-#{@size}",
55
+ @gap && "is-gap-#{@gap}",
56
+ @columns && "has-#{@columns}-cols"
57
+ ]
58
+ end
59
+
60
+ private
61
+
62
+ def any_columns?
63
+ instance_variables.grep(/columns/).any? { |var| instance_variable_get(var).to_i.positive? }
64
+ end
65
+
66
+ class Cell < BaseComponent
67
+ option :from_start, values: (0..12).to_a.push(nil), default: nil
68
+ option :from_end, values: (0..12).to_a.push(nil), default: nil
69
+
70
+ option :row_start, values: (0..12).to_a.push(nil), default: nil
71
+ option :row_end, values: (0..12).to_a.push(nil), default: nil
72
+
73
+ option :span, values: (0..12).to_a.push(nil), default: nil
74
+ option :row_span, values: (0..12).to_a.push(nil), default: nil
75
+
76
+ def root_classes
77
+ super +
78
+ [
79
+ 'cell',
80
+ @from_start && "is-col-start-#{@from_start}",
81
+ @from_end && "is-col-from-end-#{@from_end}",
82
+ @span && "is-col-span-#{@span}",
83
+ @row_start && "is-row-start-#{@row_start}",
84
+ @row_end && "is-row-from-end-#{@row_end}",
85
+ @row_span && "is-row-span-#{@row_span}"
86
+ ]
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Help < BaseComponent
5
+ root_slot tag: :span, classes: ['help']
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Hero < BaseComponent
5
+ option :modifier, values: MODIFIERS, default: nil
6
+ option :size, values: %i[small medium large halfheight fullheight fullheight-with-navbar], default: 'medium'
7
+
8
+ root_slot tag: :section
9
+ slot :header, component: 'HeroPart'
10
+ slot :body, component: 'HeroPart'
11
+ slot :footer, component: 'HeroPart'
12
+
13
+ def view_template
14
+ super do
15
+ slot(:header, type: :head) if slot?(:header)
16
+ slot(:body, type: :body)
17
+ slot(:footer, type: :foot) if slot?(:footer)
18
+ end
19
+ end
20
+
21
+ def root_classes
22
+ super +
23
+ [
24
+ 'hero',
25
+ "is-#{@size}",
26
+ @modifier && "is-#{@modifier}"
27
+ ]
28
+ end
29
+
30
+ class HeroPart < BaseComponent
31
+ option :type, values: %i[head body foot]
32
+
33
+ def root_classes = super + ["hero-#{@type}"]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Icon < BaseComponent
5
+ option :icon
6
+ option :icon_alignment, values: [nil, :left, :right], default: nil
7
+ option :control_alignment, values: [nil, :left, :right], default: nil
8
+ option :size, values: [:small, :medium, :large, nil], default: nil
9
+
10
+ root_slot tag: :span
11
+ slot :icon_container
12
+
13
+ def view_template(&)
14
+ if block_given?
15
+ icon_text_template(&)
16
+ else
17
+ icon_template(&)
18
+ end
19
+ end
20
+
21
+ def icon_text_template(&)
22
+ slot(:icon_container) do
23
+ if @icon_alignment == :right
24
+ span(&)
25
+ render_root { icon }
26
+ else
27
+ render_root { icon }
28
+ span(&)
29
+ end
30
+ end
31
+ end
32
+
33
+ def icon_template(&)
34
+ render_root do
35
+ icon
36
+ end
37
+ end
38
+
39
+ def icon
40
+ raise NotImplementedError,
41
+ 'You must implement the icon method, using FontAwesome, Material Icons, or another icon library.'
42
+ end
43
+
44
+ def icon_container_classes
45
+ %w[
46
+ icon-text
47
+ is-align-items-center
48
+ ]
49
+ end
50
+
51
+ def root_classes
52
+ super +
53
+ [
54
+ 'icon',
55
+ @control_alignment && "is-#{@control_alignment}",
56
+ @size && "is-#{@size}"
57
+ ]
58
+ end
59
+
60
+ def icon_alignment_class
61
+ return unless @icon_alignment == :right
62
+
63
+ 'is-flex-direction-row-reverse'
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Image < BaseComponent
5
+ # TODO: Rendre src obligatoire
6
+ # HTML attributes
7
+ option :src
8
+ option :alt
9
+ option :referrerpolicy
10
+ option :crossorigin
11
+ option :width
12
+ option :height
13
+ option :sizes
14
+ option :srcset
15
+ option :loading
16
+
17
+ root_slot tag: :img
18
+
19
+ option :rounded, values: BOOLEAN, default: false
20
+
21
+ def root_classes
22
+ super +
23
+ [
24
+ @rounded && 'is-rounded'
25
+ ]
26
+ end
27
+
28
+ def root_attributes
29
+ super.merge(
30
+ src: @src,
31
+ alt: @alt,
32
+ referrerpolicy: @referrerpolicy,
33
+ crossorigin: @crossorigin,
34
+ width: @width,
35
+ height: @height,
36
+ sizes: @sizes,
37
+ srcset: @srcset,
38
+ loading: @loading
39
+ )
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Input < BaseInput
5
+ TYPES = %w[
6
+ button
7
+ checkbox
8
+ color
9
+ date
10
+ datetime-local
11
+ email
12
+ file
13
+ hidden
14
+ image
15
+ month
16
+ number
17
+ password
18
+ radio
19
+ range
20
+ reset
21
+ search
22
+ submit
23
+ tel
24
+ text
25
+ time
26
+ url
27
+ week
28
+ ].freeze
29
+
30
+ option :rounded, values: BOOLEAN, default: false
31
+ option :type, values: TYPES, default: 'text'
32
+ option :checked, values: BOOLEAN, default: false
33
+ option :name
34
+ option :value
35
+ option :placeholder
36
+
37
+ def root_classes
38
+ (super + [@rounded && 'is-rounded']).tap do |result|
39
+ result.delete('input') if %(radio checkbox button).include?(@type)
40
+ end
41
+ end
42
+
43
+ def root_attributes
44
+ super.merge(
45
+ type: @type,
46
+ checked: @checked,
47
+ name: @name,
48
+ value: @value,
49
+ placeholder: @placeholder
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Level < BaseComponent
5
+ option :mobile, values: BOOLEAN, default: false
6
+
7
+ root_slot tag: :nav
8
+
9
+ slot :left, component: 'Part'
10
+ slots :item, classes: ['level-item']
11
+ slot :right, component: 'Part'
12
+
13
+ def view_template
14
+ super do
15
+ slot(:left, side: :left) if slot?(:left)
16
+ slots(:item).each { render it }
17
+ slot(:right, side: :right) if slot?(:right)
18
+ end
19
+ end
20
+
21
+ def root_classes
22
+ super +
23
+ [
24
+ 'level',
25
+ @mobile && 'is-mobile'
26
+ ]
27
+ end
28
+
29
+ class Part < BaseComponent
30
+ option :side, values: %i[left right]
31
+
32
+ slots :item, classes: ['level-item']
33
+
34
+ def view_template
35
+ super do
36
+ slots(:item).each { render it }
37
+ end
38
+ end
39
+
40
+ def root_classes = super + ["level-#{@side}"]
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Link < BulmaX::BaseComponent
5
+ # HTML attributes
6
+ option :href, default: '#'
7
+ option :href_lang
8
+ option :ping
9
+ option :referrerpolicy
10
+ option :rel
11
+ option :target
12
+ option :type
13
+ option :download, values: BOOLEAN, default: false
14
+
15
+ root_slot tag: :a
16
+
17
+ def initialize(...)
18
+ super
19
+
20
+ @href = @href&.strip # remove leading and trailing whitespaces
21
+ end
22
+
23
+ def root_classes
24
+ super +
25
+ [
26
+ 'link'
27
+ ]
28
+ end
29
+
30
+ def root_attributes
31
+ super.merge(
32
+ href: @href,
33
+ hreflang: @href_lang,
34
+ ping: @ping,
35
+ referrerpolicy: @referrerpolicy,
36
+ rel: @rel,
37
+ target: @target,
38
+ type: @type,
39
+ title: @title,
40
+ download: @download
41
+ )
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Media < BaseComponent
5
+ root_slot tag: :article, classes: ['media']
6
+
7
+ slot :left, classes: ['media-left']
8
+ slot :right, classes: ['media-right']
9
+ slot :content, classes: ['media-content']
10
+
11
+ def view_template
12
+ super do
13
+ slot(:left) if slot?(:left)
14
+ slot(:content)
15
+ slot(:right) if slot?(:right)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Message < BaseComponent
5
+ option :modifier, values: MODIFIERS, default: nil
6
+
7
+ root_slot tag: :article
8
+
9
+ slot :header, classes: ['message-header']
10
+ slot :body, classes: ['message-body']
11
+
12
+ def view_template
13
+ super do
14
+ slot(:header) if slot?(:header)
15
+ slot(:body)
16
+ end
17
+ end
18
+
19
+ def root_classes
20
+ super +
21
+ [
22
+ 'message',
23
+ @modifier && "is-#{@modifier}"
24
+ ]
25
+ end
26
+ end
27
+ end