govuk_design_system_formbuilder 1.2.0b1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +2 -1
  4. data/lib/govuk_design_system_formbuilder/base.rb +5 -0
  5. data/lib/govuk_design_system_formbuilder/builder.rb +205 -77
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +12 -11
  7. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +32 -16
  8. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +12 -11
  9. data/lib/govuk_design_system_formbuilder/elements/caption.rb +34 -0
  10. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +11 -13
  11. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +17 -15
  12. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +20 -27
  13. data/lib/govuk_design_system_formbuilder/elements/date.rb +23 -25
  14. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +8 -7
  15. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +23 -26
  16. data/lib/govuk_design_system_formbuilder/elements/file.rb +18 -19
  17. data/lib/govuk_design_system_formbuilder/elements/hint.rb +1 -4
  18. data/lib/govuk_design_system_formbuilder/elements/label.rb +30 -19
  19. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +26 -24
  20. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +13 -13
  21. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +15 -19
  22. data/lib/govuk_design_system_formbuilder/elements/select.rb +8 -18
  23. data/lib/govuk_design_system_formbuilder/elements/submit.rb +27 -23
  24. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +17 -23
  25. data/lib/govuk_design_system_formbuilder/traits/caption.rb +23 -0
  26. data/lib/govuk_design_system_formbuilder/traits/input.rb +19 -27
  27. data/lib/govuk_design_system_formbuilder/traits/label.rb +12 -1
  28. data/lib/govuk_design_system_formbuilder/traits/localisation.rb +2 -0
  29. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  30. metadata +21 -47
@@ -4,10 +4,11 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Error
5
5
  include Traits::Hint
6
6
 
7
- def initialize(builder, object_name, attribute_name, hint_text:, legend:, small:, classes:, &block)
7
+ def initialize(builder, object_name, attribute_name, hint_text:, legend:, caption:, small:, classes:, &block)
8
8
  super(builder, object_name, attribute_name, &block)
9
9
 
10
10
  @legend = legend
11
+ @caption = caption
11
12
  @hint_text = hint_text
12
13
  @small = small
13
14
  @classes = classes
@@ -16,19 +17,19 @@ module GOVUKDesignSystemFormBuilder
16
17
 
17
18
  def html
18
19
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
19
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
20
- safe_join(
21
- [
22
- hint_element.html,
23
- error_element.html,
24
- Containers::CheckBoxes.new(@builder, small: @small, classes: @classes).html do
25
- @block_content
26
- end
27
- ]
28
- )
20
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_element.error_id, hint_element.hint_id]).html do
21
+ safe_join([hint_element, error_element, checkboxes])
29
22
  end
30
23
  end
31
24
  end
25
+
26
+ private
27
+
28
+ def checkboxes
29
+ Containers::CheckBoxes.new(@builder, small: @small, classes: @classes).html do
30
+ @block_content
31
+ end
32
+ end
32
33
  end
33
34
  end
34
35
  end
@@ -3,45 +3,52 @@ module GOVUKDesignSystemFormBuilder
3
3
  class Fieldset < Base
4
4
  using PrefixableArray
5
5
 
6
+ include Traits::Caption
6
7
  include Traits::Localisation
7
8
 
8
9
  LEGEND_SIZES = %w(xl l m s).freeze
9
10
 
10
- def initialize(builder, object_name = nil, attribute_name = nil, legend: {}, described_by: nil)
11
- super(builder, object_name, attribute_name)
11
+ def initialize(builder, object_name = nil, attribute_name = nil, legend: {}, caption: {}, described_by: nil, &block)
12
+ super(builder, object_name, attribute_name, &block)
12
13
 
13
- @legend = legend_defaults.merge(legend)
14
14
  @described_by = described_by(described_by)
15
15
  @attribute_name = attribute_name
16
+
17
+ case legend
18
+ when Proc
19
+ @legend_raw = legend.call
20
+ when Hash
21
+ @legend_options = legend_defaults.merge(legend)
22
+ @caption = caption
23
+ else
24
+ fail(ArgumentError, %(legend must be a Proc or Hash))
25
+ end
16
26
  end
17
27
 
18
28
  def html
19
29
  content_tag('fieldset', class: fieldset_classes, aria: { describedby: @described_by }) do
20
- safe_join([build_legend, yield])
30
+ safe_join([legend_content, (@block_content || yield)])
21
31
  end
22
32
  end
23
33
 
24
34
  private
25
35
 
26
- def legend_defaults
27
- {
28
- hidden: false,
29
- text: nil,
30
- tag: config.default_legend_tag,
31
- size: config.default_legend_size
32
- }
36
+ def legend_content
37
+ @legend_raw || legend
33
38
  end
34
39
 
35
- def build_legend
40
+ def legend
36
41
  if legend_text.present?
37
42
  content_tag('legend', class: legend_classes) do
38
- tag.send(@legend.dig(:tag), legend_text, class: legend_heading_classes)
43
+ content_tag(@legend_options.dig(:tag), class: legend_heading_classes) do
44
+ safe_join([caption_element, legend_text])
45
+ end
39
46
  end
40
47
  end
41
48
  end
42
49
 
43
50
  def legend_text
44
- [@legend.dig(:text), localised_text(:legend)].compact.first
51
+ [@legend_options.dig(:text), localised_text(:legend)].compact.first
45
52
  end
46
53
 
47
54
  def fieldset_classes
@@ -49,17 +56,26 @@ module GOVUKDesignSystemFormBuilder
49
56
  end
50
57
 
51
58
  def legend_classes
52
- size = @legend.dig(:size)
59
+ size = @legend_options.dig(:size)
53
60
  fail "invalid size '#{size}', must be #{LEGEND_SIZES.join(', ')}" unless size.in?(LEGEND_SIZES)
54
61
 
55
62
  [%(fieldset__legend), %(fieldset__legend--#{size})].prefix(brand).tap do |classes|
56
- classes.push(%(#{brand}-visually-hidden)) if @legend.dig(:hidden)
63
+ classes.push(%(#{brand}-visually-hidden)) if @legend_options.dig(:hidden)
57
64
  end
58
65
  end
59
66
 
60
67
  def legend_heading_classes
61
68
  %w(fieldset__heading).prefix(brand)
62
69
  end
70
+
71
+ def legend_defaults
72
+ {
73
+ hidden: false,
74
+ text: nil,
75
+ tag: config.default_legend_tag,
76
+ size: config.default_legend_size
77
+ }
78
+ end
63
79
  end
64
80
  end
65
81
  end
@@ -4,12 +4,13 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Hint
5
5
  include Traits::Error
6
6
 
7
- def initialize(builder, object_name, attribute_name, hint_text:, legend:, inline:, small:, classes:, &block)
7
+ def initialize(builder, object_name, attribute_name, hint_text:, legend:, caption:, inline:, small:, classes:, &block)
8
8
  super(builder, object_name, attribute_name)
9
9
 
10
10
  @inline = inline
11
11
  @small = small
12
12
  @legend = legend
13
+ @caption = caption
13
14
  @hint_text = hint_text
14
15
  @classes = classes
15
16
  @block_content = capture { block.call }
@@ -17,19 +18,19 @@ module GOVUKDesignSystemFormBuilder
17
18
 
18
19
  def html
19
20
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
20
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
21
- safe_join(
22
- [
23
- hint_element.html,
24
- error_element.html,
25
- Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
26
- @block_content
27
- end
28
- ]
29
- )
21
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_element.error_id, hint_element.hint_id]).html do
22
+ safe_join([hint_element, error_element, radios])
30
23
  end
31
24
  end
32
25
  end
26
+
27
+ private
28
+
29
+ def radios
30
+ Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
31
+ @block_content
32
+ end
33
+ end
33
34
  end
34
35
  end
35
36
  end
@@ -0,0 +1,34 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ class Caption < Base
4
+ include Traits::Localisation
5
+
6
+ def initialize(builder, object_name, attribute_name, text:, size: 'm')
7
+ super(builder, object_name, attribute_name)
8
+
9
+ @text = caption_text(text)
10
+ @size_class = caption_size_class(size)
11
+ end
12
+
13
+ def html
14
+ return nil if @text.blank?
15
+
16
+ tag.span(@text, class: @size_class)
17
+ end
18
+
19
+ def caption_text(override)
20
+ override || localised_text(:caption)
21
+ end
22
+
23
+ def caption_size_class(size)
24
+ case size
25
+ when 'xl' then %(#{brand}-caption-xl)
26
+ when 'l' then %(#{brand}-caption-l)
27
+ when 'm' then %(#{brand}-caption-m)
28
+ else
29
+ fail ArgumentError, "invalid size '#{size}', must be xl, l or m"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -6,7 +6,7 @@ module GOVUKDesignSystemFormBuilder
6
6
  include Traits::Hint
7
7
  include Traits::Supplemental
8
8
 
9
- def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method: nil, hint_text:, legend:, small:, classes:, &block)
9
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method: nil, hint_text:, legend:, caption:, small:, classes:, &block)
10
10
  super(builder, object_name, attribute_name, &block)
11
11
 
12
12
  @collection = collection
@@ -15,29 +15,27 @@ module GOVUKDesignSystemFormBuilder
15
15
  @hint_method = hint_method
16
16
  @small = small
17
17
  @legend = legend
18
+ @caption = caption
18
19
  @hint_text = hint_text
19
20
  @classes = classes
20
21
  end
21
22
 
22
23
  def html
23
24
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
24
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_id, hint_id, supplemental_id]).html do
25
- safe_join(
26
- [
27
- supplemental_content.html,
28
- hint_element.html,
29
- error_element.html,
30
- Containers::CheckBoxes.new(@builder, small: @small, classes: @classes).html do
31
- build_collection
32
- end
33
- ]
34
- )
25
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
26
+ safe_join([supplemental_content, hint_element, error_element, check_boxes])
35
27
  end
36
28
  end
37
29
  end
38
30
 
39
31
  private
40
32
 
33
+ def check_boxes
34
+ Containers::CheckBoxes.new(@builder, small: @small, classes: @classes).html do
35
+ collection
36
+ end
37
+ end
38
+
41
39
  # Builds a collection of check {Elements::CheckBoxes::CheckBox}
42
40
  # @return [ActiveSupport::SafeBuffer] HTML output
43
41
  #
@@ -46,7 +44,7 @@ module GOVUKDesignSystemFormBuilder
46
44
  # be rendered when it happens we need to work on the chance that it might, so
47
45
  # the +link_errors+ variable is set to +true+ if this attribute has errors and
48
46
  # always set back to +false+ after the first checkbox has been rendered
49
- def build_collection
47
+ def collection
50
48
  link_errors = has_errors?
51
49
 
52
50
  @builder.collection_check_boxes(@attribute_name, @collection, @value_method, @text_method) do |check_box|
@@ -10,31 +10,33 @@ module GOVUKDesignSystemFormBuilder
10
10
  def initialize(builder, object_name, attribute_name, checkbox, hint_method = nil, link_errors: false)
11
11
  super(builder, object_name, attribute_name)
12
12
 
13
- @checkbox = checkbox
14
- @item = checkbox.object
15
- @value = checkbox.value
16
- @hint_text = retrieve(@item, hint_method)
13
+ @checkbox = checkbox
14
+ @item = checkbox.object
15
+ @value = checkbox.value
16
+ @hint_text = retrieve(@item, hint_method)
17
17
  @link_errors = link_errors
18
18
  end
19
19
 
20
20
  def html
21
21
  content_tag('div', class: %(#{brand}-checkboxes__item)) do
22
- safe_join(
23
- [
24
- @checkbox.check_box(
25
- id: field_id(link_errors: @link_errors),
26
- class: %(#{brand}-checkboxes__input),
27
- aria: { describedby: hint_id }
28
- ),
29
- label_element.html,
30
- hint_element.html
31
- ]
32
- )
22
+ safe_join([check_box, label_element, hint_element])
33
23
  end
34
24
  end
35
25
 
36
26
  private
37
27
 
28
+ def check_box
29
+ @checkbox.check_box(**check_box_options)
30
+ end
31
+
32
+ def check_box_options
33
+ {
34
+ id: field_id(link_errors: @link_errors),
35
+ class: %(#{brand}-checkboxes__input),
36
+ aria: { describedby: hint_id }
37
+ }
38
+ end
39
+
38
40
  def label_element
39
41
  @label_element ||= Label.new(@builder, @object_name, @attribute_name, @checkbox, value: @value, link_errors: @link_errors)
40
42
  end
@@ -4,6 +4,7 @@ module GOVUKDesignSystemFormBuilder
4
4
  class FieldsetCheckBox < Base
5
5
  using PrefixableArray
6
6
 
7
+ include Traits::Label
7
8
  include Traits::Hint
8
9
  include Traits::Conditional
9
10
 
@@ -23,41 +24,33 @@ module GOVUKDesignSystemFormBuilder
23
24
  end
24
25
 
25
26
  def html
26
- safe_join(
27
- [
28
- content_tag('div', class: %(#{brand}-checkboxes__item)) do
29
- safe_join(
30
- [
31
- input,
32
- label_element.html,
33
- hint_element.html,
34
- ]
35
- )
36
- end,
37
- @conditional_content
38
- ]
39
- )
27
+ safe_join([check_box, @conditional_content])
40
28
  end
41
29
 
42
30
  private
43
31
 
32
+ def check_box
33
+ content_tag('div', class: %(#{brand}-checkboxes__item)) do
34
+ safe_join([input, label_element, hint_element])
35
+ end
36
+ end
37
+
44
38
  def input
45
- @builder.check_box(
46
- @attribute_name,
47
- {
48
- id: field_id(link_errors: @link_errors),
49
- class: check_box_classes,
50
- multiple: @multiple,
51
- aria: { describedby: hint_id },
52
- data: { 'aria-controls' => @conditional_id }
53
- },
54
- @value,
55
- false
56
- )
39
+ @builder.check_box(@attribute_name, input_options, @value, false)
40
+ end
41
+
42
+ def input_options
43
+ {
44
+ id: field_id(link_errors: @link_errors),
45
+ class: check_box_classes,
46
+ multiple: @multiple,
47
+ aria: { describedby: hint_id },
48
+ data: { 'aria-controls' => @conditional_id }
49
+ }
57
50
  end
58
51
 
59
52
  def label_element
60
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, checkbox: true, value: @value, **@label, link_errors: @link_errors)
53
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, checkbox: true, value: @value, link_errors: @link_errors, **label_options)
61
54
  end
62
55
 
63
56
  def hint_element
@@ -9,10 +9,11 @@ module GOVUKDesignSystemFormBuilder
9
9
 
10
10
  SEGMENTS = { day: '3i', month: '2i', year: '1i' }.freeze
11
11
 
12
- def initialize(builder, object_name, attribute_name, legend:, hint_text:, date_of_birth: false, omit_day:, &block)
12
+ def initialize(builder, object_name, attribute_name, legend:, caption:, hint_text:, date_of_birth: false, omit_day:, &block)
13
13
  super(builder, object_name, attribute_name, &block)
14
14
 
15
15
  @legend = legend
16
+ @caption = caption
16
17
  @hint_text = hint_text
17
18
  @date_of_birth = date_of_birth
18
19
  @omit_day = omit_day
@@ -20,23 +21,20 @@ module GOVUKDesignSystemFormBuilder
20
21
 
21
22
  def html
22
23
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
23
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_id, hint_id, supplemental_id]).html do
24
- safe_join(
25
- [
26
- supplemental_content.html,
27
- hint_element.html,
28
- error_element.html,
29
- content_tag('div', class: %(#{brand}-date-input)) do
30
- safe_join([day, month, year])
31
- end
32
- ]
33
- )
24
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
25
+ safe_join([supplemental_content, hint_element, error_element, date])
34
26
  end
35
27
  end
36
28
  end
37
29
 
38
30
  private
39
31
 
32
+ def date
33
+ content_tag('div', class: %(#{brand}-date-input)) do
34
+ safe_join([day, month, year])
35
+ end
36
+ end
37
+
40
38
  def omit_day?
41
39
  @omit_day
42
40
  end
@@ -44,18 +42,18 @@ module GOVUKDesignSystemFormBuilder
44
42
  def day
45
43
  return nil if omit_day?
46
44
 
47
- date_input_item(:day, link_errors: true)
45
+ date_part_input(:day, link_errors: true)
48
46
  end
49
47
 
50
48
  def month
51
- date_input_item(:month, link_errors: omit_day?)
49
+ date_part_input(:month, link_errors: omit_day?)
52
50
  end
53
51
 
54
52
  def year
55
- date_input_item(:year, width: 4)
53
+ date_part_input(:year, width: 4)
56
54
  end
57
55
 
58
- def date_input_item(segment, width: 2, link_errors: false)
56
+ def date_part_input(segment, width: 2, link_errors: false)
59
57
  value = @builder.object.try(@attribute_name).try(segment)
60
58
 
61
59
  content_tag('div', class: %w(date-input__item).prefix(brand)) do
@@ -64,14 +62,14 @@ module GOVUKDesignSystemFormBuilder
64
62
  [
65
63
  tag.label(
66
64
  segment.capitalize,
67
- class: date_input_label_classes,
68
- for: date_attribute_id(segment, link_errors)
65
+ class: date_part_label_classes,
66
+ for: date_part_attribute_id(segment, link_errors)
69
67
  ),
70
68
 
71
69
  tag.input(
72
- id: date_attribute_id(segment, link_errors),
73
- class: date_input_classes(width),
74
- name: date_attribute_name(segment),
70
+ id: date_part_attribute_id(segment, link_errors),
71
+ class: date_part_input_classes(width),
72
+ name: date_part_attribute_name(segment),
75
73
  type: 'text',
76
74
  pattern: '[0-9]*',
77
75
  inputmode: 'numeric',
@@ -84,21 +82,21 @@ module GOVUKDesignSystemFormBuilder
84
82
  end
85
83
  end
86
84
 
87
- def date_input_classes(width)
85
+ def date_part_input_classes(width)
88
86
  %w(input date-input__input).prefix(brand).tap do |classes|
89
87
  classes.push(%(#{brand}-input--width-#{width}))
90
88
  classes.push(%(#{brand}-input--error)) if has_errors?
91
89
  end
92
90
  end
93
91
 
94
- def date_input_label_classes
92
+ def date_part_label_classes
95
93
  %w(label date-input__label).prefix(brand)
96
94
  end
97
95
 
98
96
  # if the field has errors we want the govuk_error_summary to
99
97
  # be able to link to the day field. Otherwise, generate IDs
100
98
  # in the normal fashion
101
- def date_attribute_id(segment, link_errors)
99
+ def date_part_attribute_id(segment, link_errors)
102
100
  if has_errors? && link_errors
103
101
  field_id(link_errors: link_errors)
104
102
  else
@@ -106,7 +104,7 @@ module GOVUKDesignSystemFormBuilder
106
104
  end
107
105
  end
108
106
 
109
- def date_attribute_name(segment)
107
+ def date_part_attribute_name(segment)
110
108
  format(
111
109
  "%<object_name>s[%<attribute_name>s(%<segment>s)]",
112
110
  object_name: @object_name,