govuk_design_system_formbuilder 1.2.0 → 1.2.5

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 (35) 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 +52 -33
  5. data/lib/govuk_design_system_formbuilder/containers/character_count.rb +8 -7
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +18 -10
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +27 -18
  8. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +15 -55
  9. data/lib/govuk_design_system_formbuilder/containers/form_group.rb +18 -10
  10. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +28 -19
  11. data/lib/govuk_design_system_formbuilder/containers/radios.rb +22 -11
  12. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +3 -3
  13. data/lib/govuk_design_system_formbuilder/elements/caption.rb +8 -6
  14. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +29 -23
  15. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +17 -15
  16. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +28 -32
  17. data/lib/govuk_design_system_formbuilder/elements/date.rb +55 -51
  18. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +7 -6
  19. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +24 -27
  20. data/lib/govuk_design_system_formbuilder/elements/file.rb +21 -22
  21. data/lib/govuk_design_system_formbuilder/elements/hint.rb +13 -16
  22. data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +2 -0
  23. data/lib/govuk_design_system_formbuilder/elements/label.rb +40 -29
  24. data/lib/govuk_design_system_formbuilder/elements/legend.rb +79 -0
  25. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +46 -36
  26. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +24 -14
  27. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +18 -19
  28. data/lib/govuk_design_system_formbuilder/elements/select.rb +28 -34
  29. data/lib/govuk_design_system_formbuilder/elements/submit.rb +34 -25
  30. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +39 -40
  31. data/lib/govuk_design_system_formbuilder/traits/caption.rb +5 -6
  32. data/lib/govuk_design_system_formbuilder/traits/input.rb +21 -29
  33. data/lib/govuk_design_system_formbuilder/traits/label.rb +2 -2
  34. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  35. metadata +16 -15
@@ -9,35 +9,37 @@ 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:, caption:, 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:, form_group_classes:, &block)
13
13
  super(builder, object_name, attribute_name, &block)
14
14
 
15
- @legend = legend
16
- @caption = caption
17
- @hint_text = hint_text
18
- @date_of_birth = date_of_birth
19
- @omit_day = omit_day
15
+ @legend = legend
16
+ @caption = caption
17
+ @hint_text = hint_text
18
+ @date_of_birth = date_of_birth
19
+ @omit_day = omit_day
20
+ @form_group_classes = form_group_classes
20
21
  end
21
22
 
22
23
  def html
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::FormGroup.new(@builder, @object_name, @attribute_name, classes: @form_group_classes).html do
25
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
26
+ safe_join([supplemental_content, hint_element, error_element, date])
35
27
  end
36
28
  end
37
29
  end
38
30
 
39
31
  private
40
32
 
33
+ def fieldset_options
34
+ { legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id] }
35
+ end
36
+
37
+ def date
38
+ content_tag('div', class: %(#{brand}-date-input)) do
39
+ safe_join([day, month, year])
40
+ end
41
+ end
42
+
41
43
  def omit_day?
42
44
  @omit_day
43
45
  end
@@ -45,61 +47,59 @@ module GOVUKDesignSystemFormBuilder
45
47
  def day
46
48
  return nil if omit_day?
47
49
 
48
- date_input_item(:day, link_errors: true)
50
+ date_part(:day, width: 2, link_errors: true)
49
51
  end
50
52
 
51
53
  def month
52
- date_input_item(:month, link_errors: omit_day?)
54
+ date_part(:month, width: 2, link_errors: omit_day?)
53
55
  end
54
56
 
55
57
  def year
56
- date_input_item(:year, width: 4)
58
+ date_part(:year, width: 4)
57
59
  end
58
60
 
59
- def date_input_item(segment, width: 2, link_errors: false)
61
+ def date_part(segment, width:, link_errors: false)
60
62
  value = @builder.object.try(@attribute_name).try(segment)
61
63
 
62
64
  content_tag('div', class: %w(date-input__item).prefix(brand)) do
63
65
  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
- )
66
+ safe_join([label(segment, link_errors), input(segment, link_errors, width, value)])
84
67
  end
85
68
  end
86
69
  end
87
70
 
88
- def date_input_classes(width)
71
+ def label(segment, link_errors)
72
+ tag.label(
73
+ segment.capitalize,
74
+ class: label_classes,
75
+ for: id(segment, link_errors)
76
+ )
77
+ end
78
+
79
+ def input(segment, link_errors, width, value)
80
+ tag.input(
81
+ id: id(segment, link_errors),
82
+ class: classes(width),
83
+ name: name(segment),
84
+ type: 'text',
85
+ pattern: '[0-9]*',
86
+ inputmode: 'numeric',
87
+ value: value,
88
+ autocomplete: date_of_birth_autocomplete_value(segment)
89
+ )
90
+ end
91
+
92
+ def classes(width)
89
93
  %w(input date-input__input).prefix(brand).tap do |classes|
90
94
  classes.push(%(#{brand}-input--width-#{width}))
91
95
  classes.push(%(#{brand}-input--error)) if has_errors?
92
96
  end
93
97
  end
94
98
 
95
- def date_input_label_classes
96
- %w(label date-input__label).prefix(brand)
97
- end
98
-
99
99
  # if the field has errors we want the govuk_error_summary to
100
100
  # be able to link to the day field. Otherwise, generate IDs
101
101
  # in the normal fashion
102
- def date_attribute_id(segment, link_errors)
102
+ def id(segment, link_errors)
103
103
  if has_errors? && link_errors
104
104
  field_id(link_errors: link_errors)
105
105
  else
@@ -107,11 +107,11 @@ module GOVUKDesignSystemFormBuilder
107
107
  end
108
108
  end
109
109
 
110
- def date_attribute_name(segment)
110
+ def name(segment)
111
111
  format(
112
- "%<object_name>s[%<attribute_name>s(%<segment>s)]",
112
+ "%<object_name>s[%<input_name>s(%<segment>s)]",
113
113
  object_name: @object_name,
114
- attribute_name: @attribute_name,
114
+ input_name: @attribute_name,
115
115
  segment: SEGMENTS.fetch(segment)
116
116
  )
117
117
  end
@@ -121,6 +121,10 @@ module GOVUKDesignSystemFormBuilder
121
121
 
122
122
  { day: 'bday-day', month: 'bday-month', year: 'bday-year' }.fetch(segment)
123
123
  end
124
+
125
+ def label_classes
126
+ %w(label date-input__label).prefix(brand)
127
+ end
124
128
  end
125
129
  end
126
130
  end
@@ -13,15 +13,16 @@ 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([prefix, message])
22
17
  end
23
18
  end
24
19
 
20
+ private
21
+
22
+ def prefix
23
+ tag.span('Error: ', class: %(#{brand}-visually-hidden))
24
+ end
25
+
25
26
  def message
26
27
  @builder.object.errors.messages[@attribute_name]&.first
27
28
  end
@@ -12,38 +12,35 @@ 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: summary_class, **summary_options) do
16
+ safe_join([title, 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 title
23
+ tag.h2(@title, id: summary_title_id, class: summary_class('title'))
24
+ end
25
+
26
+ def summary
27
+ content_tag('div', class: summary_class('body')) do
28
+ content_tag('ul', class: [%(#{brand}-list), summary_class('list')]) do
29
+ safe_join(list)
30
+ end
44
31
  end
45
32
  end
46
33
 
34
+ def list
35
+ @builder.object.errors.messages.map do |attribute, messages|
36
+ list_item(attribute, messages.first)
37
+ end
38
+ end
39
+
40
+ def 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
@@ -60,7 +57,7 @@ module GOVUKDesignSystemFormBuilder
60
57
  build_id('field-error', attribute_name: attribute)
61
58
  end
62
59
 
63
- def error_summary_title_id
60
+ def summary_title_id
64
61
  'error-summary-title'
65
62
  end
66
63
 
@@ -68,7 +65,7 @@ module GOVUKDesignSystemFormBuilder
68
65
  @builder.object.errors.any?
69
66
  end
70
67
 
71
- def error_summary_attributes
68
+ def summary_options
72
69
  {
73
70
  tabindex: -1,
74
71
  role: 'alert',
@@ -76,7 +73,7 @@ module GOVUKDesignSystemFormBuilder
76
73
  module: %(#{brand}-error-summary)
77
74
  },
78
75
  aria: {
79
- labelledby: error_summary_title_id
76
+ labelledby: summary_title_id
80
77
  }
81
78
  }
82
79
  end
@@ -8,38 +8,37 @@ 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:, form_group_classes:, **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
+ @form_group_classes = form_group_classes
18
19
  end
19
20
 
20
21
  def html
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
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, classes: @form_group_classes).html do
23
+ safe_join([label_element, supplemental_content, hint_element, error_element, file])
37
24
  end
38
25
  end
39
26
 
40
27
  private
41
28
 
42
- def file_classes
29
+ def file
30
+ @builder.file_field(@attribute_name, **options, **@extra_options)
31
+ end
32
+
33
+ def options
34
+ {
35
+ id: field_id(link_errors: true),
36
+ class: classes,
37
+ aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
38
+ }
39
+ end
40
+
41
+ def classes
43
42
  %w(file-upload).prefix(brand).tap do |c|
44
43
  c.push(%(#{brand}-file-upload--error)) if has_errors?
45
44
  end
@@ -9,37 +9,34 @@ 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 = retrieve_text(text)
14
+ @radio = radio
15
+ @checkbox = checkbox
16
16
  end
17
17
 
18
18
  def html
19
19
  return nil if @hint_text.blank?
20
20
 
21
- tag.span(@hint_text, class: hint_classes, id: hint_id)
21
+ tag.span(@hint_text, class: classes, id: hint_id)
22
22
  end
23
23
 
24
24
  private
25
25
 
26
- def hint_text(supplied)
27
- [
28
- supplied.presence,
29
- localised_text(:hint)
30
- ].compact.first
26
+ def retrieve_text(supplied)
27
+ supplied.presence || localised_text(:hint)
31
28
  end
32
29
 
33
- def hint_classes
34
- %w(hint).prefix(brand).push(@radio_class, @checkbox_class).compact
30
+ def classes
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
@@ -10,6 +10,8 @@ module GOVUKDesignSystemFormBuilder
10
10
  include Traits::Label
11
11
  include Traits::Supplemental
12
12
 
13
+ private
14
+
13
15
  def builder_method
14
16
  :email_field
15
17
  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 = retrieve_text(text, hidden)
19
+ @size_class = 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,26 +29,21 @@ 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, **options) do
42
+ @content || safe_join([caption, @text])
48
43
  end
49
44
  end
50
45
 
51
- def label_text(option_text, hidden)
46
+ def retrieve_text(option_text, hidden)
52
47
  text = [option_text, localised_text(:label), @attribute_name.capitalize].compact.first.to_s
53
48
 
54
49
  if hidden
@@ -58,21 +53,37 @@ module GOVUKDesignSystemFormBuilder
58
53
  end
59
54
  end
60
55
 
61
- def radio_class(radio)
62
- radio ? %(#{brand}-radios__label) : nil
56
+ def 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
- def label_size_class(size)
80
+ def size_class(size)
70
81
  case size
71
- when 'xl' then %(#{brand}-label--xl)
72
- when 'l' then %(#{brand}-label--l)
73
- when 'm' then %(#{brand}-label--m)
74
- when 's' then %(#{brand}-label--s)
75
- when nil then nil
82
+ when 'xl' then %(#{brand}-label--xl)
83
+ when 'l' then %(#{brand}-label--l)
84
+ when 'm' then %(#{brand}-label--m)
85
+ when 's' then %(#{brand}-label--s)
86
+ when nil then nil
76
87
  else
77
88
  fail "invalid size '#{size}', must be xl, l, m, s or nil"
78
89
  end