govuk_design_system_formbuilder 1.2.0b4 → 1.2.4

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/govuk_design_system_formbuilder.rb +4 -0
  3. data/lib/govuk_design_system_formbuilder/base.rb +5 -0
  4. data/lib/govuk_design_system_formbuilder/builder.rb +6 -4
  5. data/lib/govuk_design_system_formbuilder/containers/character_count.rb +8 -7
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +8 -1
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +18 -10
  8. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +23 -13
  9. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +18 -10
  10. data/lib/govuk_design_system_formbuilder/containers/radios.rb +8 -1
  11. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +1 -3
  12. data/lib/govuk_design_system_formbuilder/elements/caption.rb +2 -2
  13. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +17 -12
  14. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +17 -15
  15. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +23 -27
  16. data/lib/govuk_design_system_formbuilder/elements/date.rb +44 -41
  17. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +8 -7
  18. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +23 -26
  19. data/lib/govuk_design_system_formbuilder/elements/file.rb +18 -20
  20. data/lib/govuk_design_system_formbuilder/elements/hint.rb +10 -13
  21. data/lib/govuk_design_system_formbuilder/elements/label.rb +33 -22
  22. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +32 -23
  23. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +24 -14
  24. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +18 -19
  25. data/lib/govuk_design_system_formbuilder/elements/select.rb +15 -22
  26. data/lib/govuk_design_system_formbuilder/elements/submit.rb +29 -25
  27. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +37 -39
  28. data/lib/govuk_design_system_formbuilder/traits/caption.rb +5 -6
  29. data/lib/govuk_design_system_formbuilder/traits/input.rb +19 -28
  30. data/lib/govuk_design_system_formbuilder/traits/label.rb +2 -2
  31. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  32. metadata +17 -17
@@ -21,23 +21,24 @@ module GOVUKDesignSystemFormBuilder
21
21
 
22
22
  def html
23
23
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
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(
26
- [
27
- supplemental_content.html,
28
- hint_element.html,
29
- error_element.html,
30
- content_tag('div', class: %(#{brand}-date-input)) do
31
- safe_join([day, month, year])
32
- end
33
- ]
34
- )
24
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
25
+ safe_join([supplemental_content, hint_element, error_element, date])
35
26
  end
36
27
  end
37
28
  end
38
29
 
39
30
  private
40
31
 
32
+ def fieldset_options
33
+ { legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id] }
34
+ end
35
+
36
+ def date
37
+ content_tag('div', class: %(#{brand}-date-input)) do
38
+ safe_join([day, month, year])
39
+ end
40
+ end
41
+
41
42
  def omit_day?
42
43
  @omit_day
43
44
  end
@@ -45,61 +46,63 @@ module GOVUKDesignSystemFormBuilder
45
46
  def day
46
47
  return nil if omit_day?
47
48
 
48
- date_input_item(:day, link_errors: true)
49
+ date_part(:day, width: 2, link_errors: true)
49
50
  end
50
51
 
51
52
  def month
52
- date_input_item(:month, link_errors: omit_day?)
53
+ date_part(:month, width: 2, link_errors: omit_day?)
53
54
  end
54
55
 
55
56
  def year
56
- date_input_item(:year, width: 4)
57
+ date_part(:year, width: 4)
57
58
  end
58
59
 
59
- def date_input_item(segment, width: 2, link_errors: false)
60
+ def date_part(segment, width:, link_errors: false)
60
61
  value = @builder.object.try(@attribute_name).try(segment)
61
62
 
62
63
  content_tag('div', class: %w(date-input__item).prefix(brand)) do
63
64
  content_tag('div', class: %w(form-group).prefix(brand)) do
64
- safe_join(
65
- [
66
- tag.label(
67
- segment.capitalize,
68
- class: date_input_label_classes,
69
- for: date_attribute_id(segment, link_errors)
70
- ),
71
-
72
- tag.input(
73
- id: date_attribute_id(segment, link_errors),
74
- class: date_input_classes(width),
75
- name: date_attribute_name(segment),
76
- type: 'text',
77
- pattern: '[0-9]*',
78
- inputmode: 'numeric',
79
- value: value,
80
- autocomplete: date_of_birth_autocomplete_value(segment)
81
- )
82
- ]
83
- )
65
+ safe_join([label(segment, link_errors), input(segment, link_errors, width, value)])
84
66
  end
85
67
  end
86
68
  end
87
69
 
88
- def date_input_classes(width)
70
+ def label(segment, link_errors)
71
+ tag.label(
72
+ segment.capitalize,
73
+ class: label_classes,
74
+ for: input_id(segment, link_errors)
75
+ )
76
+ end
77
+
78
+ def input(segment, link_errors, width, value)
79
+ tag.input(
80
+ id: input_id(segment, link_errors),
81
+ class: input_classes(width),
82
+ name: input_name(segment),
83
+ type: 'text',
84
+ pattern: '[0-9]*',
85
+ inputmode: 'numeric',
86
+ value: value,
87
+ autocomplete: date_of_birth_autocomplete_value(segment)
88
+ )
89
+ end
90
+
91
+ def input_classes(width)
89
92
  %w(input date-input__input).prefix(brand).tap do |classes|
90
93
  classes.push(%(#{brand}-input--width-#{width}))
91
94
  classes.push(%(#{brand}-input--error)) if has_errors?
92
95
  end
93
96
  end
94
97
 
95
- def date_input_label_classes
98
+ def label_classes
96
99
  %w(label date-input__label).prefix(brand)
97
100
  end
98
101
 
99
102
  # if the field has errors we want the govuk_error_summary to
100
103
  # be able to link to the day field. Otherwise, generate IDs
101
104
  # in the normal fashion
102
- def date_attribute_id(segment, link_errors)
105
+ def input_id(segment, link_errors)
103
106
  if has_errors? && link_errors
104
107
  field_id(link_errors: link_errors)
105
108
  else
@@ -107,11 +110,11 @@ module GOVUKDesignSystemFormBuilder
107
110
  end
108
111
  end
109
112
 
110
- def date_attribute_name(segment)
113
+ def input_name(segment)
111
114
  format(
112
- "%<object_name>s[%<attribute_name>s(%<segment>s)]",
115
+ "%<object_name>s[%<input_name>s(%<segment>s)]",
113
116
  object_name: @object_name,
114
- attribute_name: @attribute_name,
117
+ input_name: @attribute_name,
115
118
  segment: SEGMENTS.fetch(segment)
116
119
  )
117
120
  end
@@ -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,37 +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:, caption:, **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
- @caption = caption
16
- @hint_text = hint_text
17
- @extra_args = extra_args
14
+ @label = label
15
+ @caption = caption
16
+ @hint_text = hint_text
17
+ @extra_options = kwargs
18
18
  end
19
19
 
20
20
  def html
21
21
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
22
- safe_join(
23
- [
24
- label_element.html,
25
- supplemental_content.html,
26
- hint_element.html,
27
- error_element.html,
28
- @builder.file_field(
29
- @attribute_name,
30
- id: field_id(link_errors: true),
31
- class: file_classes,
32
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) },
33
- **@extra_args
34
- )
35
- ]
36
- )
22
+ safe_join([label_element, supplemental_content, hint_element, error_element, file])
37
23
  end
38
24
  end
39
25
 
40
26
  private
41
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
+
42
40
  def file_classes
43
41
  %w(file-upload).prefix(brand).tap do |c|
44
42
  c.push(%(#{brand}-file-upload--error)) if has_errors?
@@ -9,10 +9,10 @@ module GOVUKDesignSystemFormBuilder
9
9
  def initialize(builder, object_name, attribute_name, text, value = nil, radio: false, checkbox: false)
10
10
  super(builder, object_name, attribute_name)
11
11
 
12
- @value = value
13
- @hint_text = hint_text(text)
14
- @radio_class = radio_class(radio)
15
- @checkbox_class = checkbox_class(checkbox)
12
+ @value = value
13
+ @hint_text = hint_text(text)
14
+ @radio = radio
15
+ @checkbox = checkbox
16
16
  end
17
17
 
18
18
  def html
@@ -24,22 +24,19 @@ 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)
31
28
  end
32
29
 
33
30
  def hint_classes
34
- %w(hint).prefix(brand).push(@radio_class, @checkbox_class).compact
31
+ %w(hint).prefix(brand).push(radio_class, checkbox_class).compact
35
32
  end
36
33
 
37
- def radio_class(radio)
38
- radio ? %(#{brand}-radios__hint) : nil
34
+ def radio_class
35
+ @radio ? %(#{brand}-radios__hint) : nil
39
36
  end
40
37
 
41
- def checkbox_class(checkbox)
42
- checkbox ? %(#{brand}-checkboxes__hint) : nil
38
+ def checkbox_class
39
+ @checkbox ? %(#{brand}-checkboxes__hint) : nil
43
40
  end
44
41
  end
45
42
  end
@@ -14,14 +14,14 @@ module GOVUKDesignSystemFormBuilder
14
14
  if content
15
15
  @content = content.call
16
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
17
+ @value = value # used by field_id
18
+ @text = label_text(text, hidden)
19
+ @size_class = label_size_class(size)
20
+ @radio = radio
21
+ @checkbox = checkbox
22
+ @tag = tag
23
+ @link_errors = link_errors
24
+ @caption = caption
25
25
  end
26
26
  end
27
27
 
@@ -29,22 +29,17 @@ module GOVUKDesignSystemFormBuilder
29
29
  return nil if [@content, @text].all?(&:blank?)
30
30
 
31
31
  if @tag.present?
32
- content_tag(@tag, class: %(#{brand}-label-wrapper)) { build_label }
32
+ content_tag(@tag, class: %(#{brand}-label-wrapper)) { label }
33
33
  else
34
- build_label
34
+ label
35
35
  end
36
36
  end
37
37
 
38
38
  private
39
39
 
40
- def build_label
41
- @builder.label(
42
- @attribute_name,
43
- value: @value,
44
- for: field_id(link_errors: @link_errors),
45
- class: %w(label).prefix(brand).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
46
- ) do
47
- @content || safe_join([caption_element.html, @text])
40
+ def label
41
+ @builder.label(@attribute_name, **label_options) do
42
+ @content || safe_join([caption, @text])
48
43
  end
49
44
  end
50
45
 
@@ -58,12 +53,28 @@ module GOVUKDesignSystemFormBuilder
58
53
  end
59
54
  end
60
55
 
61
- def radio_class(radio)
62
- radio ? %(#{brand}-radios__label) : nil
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
+
64
+ def caption
65
+ caption_element.html unless [@radio, @checkbox].any?
63
66
  end
64
67
 
65
- def checkbox_class(checkbox)
66
- checkbox ? %(#{brand}-checkboxes__label) : nil
68
+ def radio_class
69
+ return nil unless @radio
70
+
71
+ %(#{brand}-radios__label)
72
+ end
73
+
74
+ def checkbox_class
75
+ return nil unless @checkbox
76
+
77
+ %(#{brand}-checkboxes__label)
67
78
  end
68
79
 
69
80
  def label_size_class(size)
@@ -24,38 +24,47 @@ module GOVUKDesignSystemFormBuilder
24
24
 
25
25
  def html
26
26
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
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(
29
- [
30
- supplemental_content.html,
31
- hint_element.html,
32
- error_element.html,
33
- Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
34
- safe_join(build_collection)
35
- end
36
- ]
37
- )
27
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
28
+ safe_join([supplemental_content, hint_element, error_element, radios])
38
29
  end
39
30
  end
40
31
  end
41
32
 
42
33
  private
43
34
 
44
- def build_collection
35
+ def fieldset_options
36
+ {
37
+ legend: @legend,
38
+ caption: @caption,
39
+ described_by: [error_id, hint_id, supplemental_id]
40
+ }
41
+ end
42
+
43
+ def radios
44
+ Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
45
+ safe_join(collection)
46
+ end
47
+ end
48
+
49
+ def collection
45
50
  @collection.map.with_index do |item, i|
46
- Elements::Radios::CollectionRadioButton.new(
47
- @builder,
48
- @object_name,
49
- @attribute_name,
50
- item,
51
- value_method: @value_method,
52
- text_method: @text_method,
53
- hint_method: @hint_method,
54
- link_errors: has_errors? && i.zero?,
55
- bold_labels: @bold_labels
56
- ).html
51
+ Elements::Radios::CollectionRadioButton.new(@builder, @object_name, @attribute_name, item, **collection_options(i)).html
57
52
  end
58
53
  end
54
+
55
+ def collection_options(index)
56
+ {
57
+ value_method: @value_method,
58
+ text_method: @text_method,
59
+ hint_method: @hint_method,
60
+ link_errors: link_errors?(index),
61
+ bold_labels: @bold_labels
62
+ }
63
+ end
64
+
65
+ def link_errors?(index)
66
+ has_errors? && index.zero?
67
+ end
59
68
  end
60
69
  end
61
70
  end