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
@@ -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,