govuk_design_system_formbuilder 1.2.0 → 1.2.5

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