govuk_design_system_formbuilder 1.2.0b1 → 1.2.2

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 (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
@@ -13,16 +13,17 @@ module GOVUKDesignSystemFormBuilder
13
13
  return nil unless has_errors?
14
14
 
15
15
  content_tag('span', class: %(#{brand}-error-message), id: error_id) do
16
- safe_join(
17
- [
18
- tag.span('Error: ', class: %(#{brand}-visually-hidden)),
19
- message
20
- ]
21
- )
16
+ safe_join([error_prefix, error_message])
22
17
  end
23
18
  end
24
19
 
25
- def message
20
+ private
21
+
22
+ def error_prefix
23
+ tag.span('Error: ', class: %(#{brand}-visually-hidden))
24
+ end
25
+
26
+ def error_message
26
27
  @builder.object.errors.messages[@attribute_name]&.first
27
28
  end
28
29
  end
@@ -12,43 +12,40 @@ module GOVUKDesignSystemFormBuilder
12
12
  def html
13
13
  return nil unless object_has_errors?
14
14
 
15
- content_tag('div', class: summary_class, **error_summary_attributes) do
16
- safe_join(
17
- [
18
- tag.h2(@title, id: error_summary_title_id, class: summary_class('title')),
19
- content_tag('div', class: summary_class('body')) do
20
- content_tag('ul', class: [%(#{brand}-list), summary_class('list')]) do
21
- safe_join(
22
- @builder.object.errors.messages.map do |attribute, messages|
23
- error_list_item(attribute, messages.first)
24
- end
25
- )
26
- end
27
- end
28
- ]
29
- )
15
+ content_tag('div', class: error_summary_class, **error_summary_options) do
16
+ safe_join([error_title, error_summary])
30
17
  end
31
18
  end
32
19
 
33
20
  private
34
21
 
35
- def error_list_item(attribute, message)
36
- content_tag('li') do
37
- link_to(
38
- message,
39
- same_page_link(field_id(attribute)),
40
- data: {
41
- turbolinks: false
42
- }
43
- )
22
+ def error_title
23
+ tag.h2(@title, id: error_summary_title_id, class: error_summary_class('title'))
24
+ end
25
+
26
+ def error_summary
27
+ content_tag('div', class: error_summary_class('body')) do
28
+ content_tag('ul', class: [%(#{brand}-list), error_summary_class('list')]) do
29
+ safe_join(error_list)
30
+ end
44
31
  end
45
32
  end
46
33
 
34
+ def error_list
35
+ @builder.object.errors.messages.map do |attribute, messages|
36
+ error_list_item(attribute, messages.first)
37
+ end
38
+ end
39
+
40
+ def error_list_item(attribute, message)
41
+ tag.li(link_to(message, same_page_link(field_id(attribute)), data: { turbolinks: false }))
42
+ end
43
+
47
44
  def same_page_link(target)
48
45
  '#'.concat(target)
49
46
  end
50
47
 
51
- def summary_class(part = nil)
48
+ def error_summary_class(part = nil)
52
49
  if part
53
50
  %(#{brand}-error-summary).concat('__', part)
54
51
  else
@@ -68,7 +65,7 @@ module GOVUKDesignSystemFormBuilder
68
65
  @builder.object.errors.any?
69
66
  end
70
67
 
71
- def error_summary_attributes
68
+ def error_summary_options
72
69
  {
73
70
  tabindex: -1,
74
71
  role: 'alert',
@@ -8,36 +8,35 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
10
 
11
- def initialize(builder, object_name, attribute_name, hint_text:, label:, **extra_args, &block)
11
+ def initialize(builder, object_name, attribute_name, hint_text:, label:, caption:, **kwargs, &block)
12
12
  super(builder, object_name, attribute_name, &block)
13
13
 
14
- @label = label
15
- @hint_text = hint_text
16
- @extra_args = extra_args
14
+ @label = label
15
+ @caption = caption
16
+ @hint_text = hint_text
17
+ @extra_options = kwargs
17
18
  end
18
19
 
19
20
  def html
20
21
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
21
- safe_join(
22
- [
23
- label_element.html,
24
- supplemental_content.html,
25
- hint_element.html,
26
- error_element.html,
27
- @builder.file_field(
28
- @attribute_name,
29
- id: field_id(link_errors: true),
30
- class: file_classes,
31
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) },
32
- **@extra_args
33
- )
34
- ]
35
- )
22
+ safe_join([label_element, supplemental_content, hint_element, error_element, file])
36
23
  end
37
24
  end
38
25
 
39
26
  private
40
27
 
28
+ def file
29
+ @builder.file_field(@attribute_name, **file_options, **@extra_options)
30
+ end
31
+
32
+ def file_options
33
+ {
34
+ id: field_id(link_errors: true),
35
+ class: file_classes,
36
+ aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
37
+ }
38
+ end
39
+
41
40
  def file_classes
42
41
  %w(file-upload).prefix(brand).tap do |c|
43
42
  c.push(%(#{brand}-file-upload--error)) if has_errors?
@@ -24,10 +24,7 @@ module GOVUKDesignSystemFormBuilder
24
24
  private
25
25
 
26
26
  def hint_text(supplied)
27
- [
28
- supplied.presence,
29
- localised_text(:hint)
30
- ].compact.first
27
+ [supplied.presence, localised_text(:hint)].compact.first
31
28
  end
32
29
 
33
30
  def hint_classes
@@ -3,40 +3,43 @@ module GOVUKDesignSystemFormBuilder
3
3
  class Label < Base
4
4
  using PrefixableArray
5
5
 
6
+ include Traits::Caption
6
7
  include Traits::Localisation
7
8
 
8
- def initialize(builder, object_name, attribute_name, text: nil, value: nil, size: nil, hidden: false, radio: false, checkbox: false, tag: nil, link_errors: true)
9
+ def initialize(builder, object_name, attribute_name, text: nil, value: nil, size: nil, hidden: false, radio: false, checkbox: false, tag: nil, link_errors: true, content: nil, caption: nil)
9
10
  super(builder, object_name, attribute_name)
10
11
 
11
- @value = value # used by field_id
12
- @text = label_text(text, hidden)
13
- @size_class = label_size_class(size)
14
- @radio_class = radio_class(radio)
15
- @checkbox_class = checkbox_class(checkbox)
16
- @tag = tag
17
- @link_errors = link_errors
12
+ # content is passed in directly via a proc and overrides
13
+ # the other display options
14
+ if content
15
+ @content = content.call
16
+ else
17
+ @value = value # used by field_id
18
+ @text = label_text(text, hidden)
19
+ @size_class = label_size_class(size)
20
+ @radio_class = radio_class(radio)
21
+ @checkbox_class = checkbox_class(checkbox)
22
+ @tag = tag
23
+ @link_errors = link_errors
24
+ @caption = caption
25
+ end
18
26
  end
19
27
 
20
28
  def html
21
- return nil if @text.blank?
29
+ return nil if [@content, @text].all?(&:blank?)
22
30
 
23
31
  if @tag.present?
24
- content_tag(@tag, class: %(#{brand}-label-wrapper)) { build_label }
32
+ content_tag(@tag, class: %(#{brand}-label-wrapper)) { label }
25
33
  else
26
- build_label
34
+ label
27
35
  end
28
36
  end
29
37
 
30
38
  private
31
39
 
32
- def build_label
33
- @builder.label(
34
- @attribute_name,
35
- value: @value,
36
- for: field_id(link_errors: @link_errors),
37
- class: %w(label).prefix(brand).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
38
- ) do
39
- @text
40
+ def label
41
+ @builder.label(@attribute_name, label_options) do
42
+ @content || safe_join([caption_element.html, @text])
40
43
  end
41
44
  end
42
45
 
@@ -50,6 +53,14 @@ module GOVUKDesignSystemFormBuilder
50
53
  end
51
54
  end
52
55
 
56
+ def label_options
57
+ {
58
+ value: @value,
59
+ for: field_id(link_errors: @link_errors),
60
+ class: %w(label).prefix(brand).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
61
+ }
62
+ end
63
+
53
64
  def radio_class(radio)
54
65
  radio ? %(#{brand}-radios__label) : nil
55
66
  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:, hint_text:, legend:, inline:, small:, bold_labels:, classes:, &block)
9
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method:, hint_text:, legend:, caption:, inline:, small:, bold_labels:, classes:, &block)
10
10
  super(builder, object_name, attribute_name, &block)
11
11
 
12
12
  @collection = collection
@@ -16,6 +16,7 @@ module GOVUKDesignSystemFormBuilder
16
16
  @inline = inline
17
17
  @small = small
18
18
  @legend = legend
19
+ @caption = caption
19
20
  @hint_text = hint_text
20
21
  @classes = classes
21
22
  @bold_labels = hint_method.present? || bold_labels
@@ -23,38 +24,39 @@ module GOVUKDesignSystemFormBuilder
23
24
 
24
25
  def html
25
26
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
26
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_id, hint_id, supplemental_id]).html do
27
- safe_join(
28
- [
29
- supplemental_content.html,
30
- hint_element.html,
31
- error_element.html,
32
- Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
33
- safe_join(build_collection)
34
- end
35
- ]
36
- )
27
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
28
+ safe_join([supplemental_content, hint_element, error_element, radios])
37
29
  end
38
30
  end
39
31
  end
40
32
 
41
33
  private
42
34
 
43
- def build_collection
35
+ def radios
36
+ Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
37
+ safe_join(collection)
38
+ end
39
+ end
40
+
41
+ def collection
44
42
  @collection.map.with_index do |item, i|
45
- Elements::Radios::CollectionRadioButton.new(
46
- @builder,
47
- @object_name,
48
- @attribute_name,
49
- item,
50
- value_method: @value_method,
51
- text_method: @text_method,
52
- hint_method: @hint_method,
53
- link_errors: has_errors? && i.zero?,
54
- bold_labels: @bold_labels
55
- ).html
43
+ Elements::Radios::CollectionRadioButton.new(@builder, @object_name, @attribute_name, item, **collection_options(i)).html
56
44
  end
57
45
  end
46
+
47
+ def collection_options(index)
48
+ {
49
+ value_method: @value_method,
50
+ text_method: @text_method,
51
+ hint_method: @hint_method,
52
+ link_errors: link_errors?(index),
53
+ bold_labels: @bold_labels
54
+ }
55
+ end
56
+
57
+ def link_errors?(index)
58
+ has_errors? && index.zero?
59
+ end
58
60
  end
59
61
  end
60
62
  end
@@ -24,24 +24,24 @@ module GOVUKDesignSystemFormBuilder
24
24
 
25
25
  def html
26
26
  content_tag('div', class: %(#{brand}-radios__item)) do
27
- safe_join(
28
- [
29
- @builder.radio_button(
30
- @attribute_name,
31
- @value,
32
- id: field_id(link_errors: @link_errors),
33
- aria: { describedby: hint_id },
34
- class: %w(radios__input).prefix(brand)
35
- ),
36
- label_element.html,
37
- hint_element.html
38
- ]
39
- )
27
+ safe_join([radio, label_element, hint_element])
40
28
  end
41
29
  end
42
30
 
43
31
  private
44
32
 
33
+ def radio
34
+ @builder.radio_button(@attribute_name, @value, **radio_options)
35
+ end
36
+
37
+ def radio_options
38
+ {
39
+ id: field_id(link_errors: @link_errors),
40
+ aria: { describedby: hint_id },
41
+ class: %w(radios__input).prefix(brand)
42
+ }
43
+ end
44
+
45
45
  def hint_element
46
46
  @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, @value, radio: true)
47
47
  end
@@ -4,6 +4,7 @@ module GOVUKDesignSystemFormBuilder
4
4
  class FieldsetRadioButton < Base
5
5
  using PrefixableArray
6
6
 
7
+ include Traits::Label
7
8
  include Traits::Hint
8
9
  include Traits::Conditional
9
10
 
@@ -22,26 +23,19 @@ module GOVUKDesignSystemFormBuilder
22
23
  end
23
24
 
24
25
  def html
25
- safe_join(
26
- [
27
- content_tag('div', class: %(#{brand}-radios__item)) do
28
- safe_join(
29
- [
30
- input,
31
- label_element.html,
32
- hint_element.html,
33
- ]
34
- )
35
- end,
36
- @conditional_content
37
- ]
38
- )
26
+ safe_join([radio, @conditional_content])
39
27
  end
40
28
 
41
29
  private
42
30
 
31
+ def radio
32
+ content_tag('div', class: %(#{brand}-radios__item)) do
33
+ safe_join([input, label_element, hint_element])
34
+ end
35
+ end
36
+
43
37
  def label_element
44
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, radio: true, value: @value, **@label, link_errors: @link_errors)
38
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, radio: true, value: @value, link_errors: @link_errors, **label_options)
45
39
  end
46
40
 
47
41
  def hint_element
@@ -49,14 +43,16 @@ module GOVUKDesignSystemFormBuilder
49
43
  end
50
44
 
51
45
  def input
52
- @builder.radio_button(
53
- @attribute_name,
54
- @value,
46
+ @builder.radio_button(@attribute_name, @value, input_options)
47
+ end
48
+
49
+ def input_options
50
+ {
55
51
  id: field_id(link_errors: @link_errors),
56
52
  aria: { describedby: hint_id },
57
53
  data: { 'aria-controls' => @conditional_id },
58
54
  class: %w(radios__input).prefix(brand)
59
- )
55
+ }
60
56
  end
61
57
 
62
58
  def conditional_classes
@@ -8,7 +8,7 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Hint
9
9
  include Traits::Supplemental
10
10
 
11
- def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, options: {}, html_options: {}, hint_text:, label:, &block)
11
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, options: {}, html_options: {}, hint_text:, label:, caption:, &block)
12
12
  super(builder, object_name, attribute_name, &block)
13
13
 
14
14
  @collection = collection
@@ -17,33 +17,23 @@ module GOVUKDesignSystemFormBuilder
17
17
  @options = options
18
18
  @html_options = html_options
19
19
  @label = label
20
+ @caption = caption
20
21
  @hint_text = hint_text
21
22
  end
22
23
 
23
24
  def html
24
25
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
25
- safe_join(
26
- [
27
- label_element.html,
28
- supplemental_content.html,
29
- hint_element.html,
30
- error_element.html,
31
- @builder.collection_select(
32
- @attribute_name,
33
- @collection,
34
- @value_method,
35
- @text_method,
36
- @options,
37
- build_html_options
38
- )
39
- ]
40
- )
26
+ safe_join([label_element, supplemental_content, hint_element, error_element, select])
41
27
  end
42
28
  end
43
29
 
44
30
  private
45
31
 
46
- def build_html_options
32
+ def select
33
+ @builder.collection_select(@attribute_name, @collection, @value_method, @text_method, @options, select_options)
34
+ end
35
+
36
+ def select_options
47
37
  @html_options.deep_merge(
48
38
  id: field_id(link_errors: true),
49
39
  class: select_classes,