govuk_design_system_formbuilder 1.2.0b4 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
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