govuk_design_system_formbuilder 1.1.11 → 1.2.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +7 -1
  4. data/lib/govuk_design_system_formbuilder/base.rb +17 -0
  5. data/lib/govuk_design_system_formbuilder/builder.rb +205 -77
  6. data/lib/govuk_design_system_formbuilder/containers/character_count.rb +2 -2
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +5 -3
  8. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +12 -11
  9. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +37 -20
  10. data/lib/govuk_design_system_formbuilder/containers/form_group.rb +4 -2
  11. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +12 -11
  12. data/lib/govuk_design_system_formbuilder/containers/radios.rb +7 -5
  13. data/lib/govuk_design_system_formbuilder/elements/caption.rb +34 -0
  14. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +11 -13
  15. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +20 -16
  16. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +24 -29
  17. data/lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb +3 -1
  18. data/lib/govuk_design_system_formbuilder/elements/date.rb +31 -31
  19. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +11 -8
  20. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +26 -29
  21. data/lib/govuk_design_system_formbuilder/elements/file.rb +22 -21
  22. data/lib/govuk_design_system_formbuilder/elements/hint.rb +6 -7
  23. data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +2 -0
  24. data/lib/govuk_design_system_formbuilder/elements/inputs/number.rb +2 -0
  25. data/lib/govuk_design_system_formbuilder/elements/inputs/password.rb +2 -0
  26. data/lib/govuk_design_system_formbuilder/elements/inputs/phone.rb +2 -0
  27. data/lib/govuk_design_system_formbuilder/elements/inputs/text.rb +2 -0
  28. data/lib/govuk_design_system_formbuilder/elements/inputs/url.rb +2 -0
  29. data/lib/govuk_design_system_formbuilder/elements/label.rb +39 -26
  30. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +26 -24
  31. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +16 -14
  32. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +19 -21
  33. data/lib/govuk_design_system_formbuilder/elements/select.rb +12 -20
  34. data/lib/govuk_design_system_formbuilder/elements/submit.rb +29 -27
  35. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +27 -27
  36. data/lib/govuk_design_system_formbuilder/traits/caption.rb +23 -0
  37. data/lib/govuk_design_system_formbuilder/traits/input.rb +33 -41
  38. data/lib/govuk_design_system_formbuilder/traits/label.rb +12 -1
  39. data/lib/govuk_design_system_formbuilder/traits/localisation.rb +2 -0
  40. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  41. metadata +19 -17
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module CheckBoxes
4
4
  class Label < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Localisation
6
8
 
7
9
  def initialize(builder, object_name, attribute_name, checkbox, value:, link_errors: true)
@@ -21,7 +23,7 @@ module GOVUKDesignSystemFormBuilder
21
23
  private
22
24
 
23
25
  def label_classes
24
- %w(govuk-label govuk-checkboxes__label)
26
+ %w(label checkboxes__label).prefix(brand)
25
27
  end
26
28
  end
27
29
  end
@@ -1,16 +1,19 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class Date < Base
4
+ using PrefixableArray
5
+
4
6
  include Traits::Error
5
7
  include Traits::Hint
6
8
  include Traits::Supplemental
7
9
 
8
10
  SEGMENTS = { day: '3i', month: '2i', year: '1i' }.freeze
9
11
 
10
- def initialize(builder, object_name, attribute_name, legend:, 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:, &block)
11
13
  super(builder, object_name, attribute_name, &block)
12
14
 
13
15
  @legend = legend
16
+ @caption = caption
14
17
  @hint_text = hint_text
15
18
  @date_of_birth = date_of_birth
16
19
  @omit_day = omit_day
@@ -18,23 +21,20 @@ module GOVUKDesignSystemFormBuilder
18
21
 
19
22
  def html
20
23
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
21
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, described_by: [error_id, hint_id, supplemental_id]).html do
22
- safe_join(
23
- [
24
- supplemental_content.html,
25
- hint_element.html,
26
- error_element.html,
27
- content_tag('div', class: 'govuk-date-input') do
28
- safe_join([day, month, year])
29
- end
30
- ]
31
- )
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([supplemental_content, hint_element, error_element, date])
32
26
  end
33
27
  end
34
28
  end
35
29
 
36
30
  private
37
31
 
32
+ def date
33
+ content_tag('div', class: %(#{brand}-date-input)) do
34
+ safe_join([day, month, year])
35
+ end
36
+ end
37
+
38
38
  def omit_day?
39
39
  @omit_day
40
40
  end
@@ -42,34 +42,34 @@ module GOVUKDesignSystemFormBuilder
42
42
  def day
43
43
  return nil if omit_day?
44
44
 
45
- date_input_item(:day, link_errors: true)
45
+ date_part_input(:day, link_errors: true)
46
46
  end
47
47
 
48
48
  def month
49
- date_input_item(:month, link_errors: omit_day?)
49
+ date_part_input(:month, link_errors: omit_day?)
50
50
  end
51
51
 
52
52
  def year
53
- date_input_item(:year, width: 4)
53
+ date_part_input(:year, width: 4)
54
54
  end
55
55
 
56
- def date_input_item(segment, width: 2, link_errors: false)
56
+ def date_part_input(segment, width: 2, link_errors: false)
57
57
  value = @builder.object.try(@attribute_name).try(segment)
58
58
 
59
- content_tag('div', class: %w(govuk-date-input__item)) do
60
- content_tag('div', class: %w(govuk-form-group)) do
59
+ content_tag('div', class: %w(date-input__item).prefix(brand)) do
60
+ content_tag('div', class: %w(form-group).prefix(brand)) do
61
61
  safe_join(
62
62
  [
63
63
  tag.label(
64
64
  segment.capitalize,
65
- class: date_input_label_classes,
66
- for: date_attribute_id(segment, link_errors)
65
+ class: date_part_label_classes,
66
+ for: date_part_attribute_id(segment, link_errors)
67
67
  ),
68
68
 
69
69
  tag.input(
70
- id: date_attribute_id(segment, link_errors),
71
- class: date_input_classes(width),
72
- name: date_attribute_name(segment),
70
+ id: date_part_attribute_id(segment, link_errors),
71
+ class: date_part_input_classes(width),
72
+ name: date_part_attribute_name(segment),
73
73
  type: 'text',
74
74
  pattern: '[0-9]*',
75
75
  inputmode: 'numeric',
@@ -82,21 +82,21 @@ module GOVUKDesignSystemFormBuilder
82
82
  end
83
83
  end
84
84
 
85
- def date_input_classes(width)
86
- %w(govuk-input govuk-date-input__input).tap do |classes|
87
- classes.push("govuk-input--width-#{width}")
88
- classes.push("govuk-input--error") if has_errors?
85
+ def date_part_input_classes(width)
86
+ %w(input date-input__input).prefix(brand).tap do |classes|
87
+ classes.push(%(#{brand}-input--width-#{width}))
88
+ classes.push(%(#{brand}-input--error)) if has_errors?
89
89
  end
90
90
  end
91
91
 
92
- def date_input_label_classes
93
- %w(govuk-label govuk-date-input__label)
92
+ def date_part_label_classes
93
+ %w(label date-input__label).prefix(brand)
94
94
  end
95
95
 
96
96
  # if the field has errors we want the govuk_error_summary to
97
97
  # be able to link to the day field. Otherwise, generate IDs
98
98
  # in the normal fashion
99
- def date_attribute_id(segment, link_errors)
99
+ def date_part_attribute_id(segment, link_errors)
100
100
  if has_errors? && link_errors
101
101
  field_id(link_errors: link_errors)
102
102
  else
@@ -104,7 +104,7 @@ module GOVUKDesignSystemFormBuilder
104
104
  end
105
105
  end
106
106
 
107
- def date_attribute_name(segment)
107
+ def date_part_attribute_name(segment)
108
108
  format(
109
109
  "%<object_name>s[%<attribute_name>s(%<segment>s)]",
110
110
  object_name: @object_name,
@@ -1,6 +1,8 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class ErrorMessage < Base
4
+ using PrefixableArray
5
+
4
6
  include Traits::Error
5
7
 
6
8
  def initialize(builder, object_name, attribute_name)
@@ -10,17 +12,18 @@ module GOVUKDesignSystemFormBuilder
10
12
  def html
11
13
  return nil unless has_errors?
12
14
 
13
- content_tag('span', class: 'govuk-error-message', id: error_id) do
14
- safe_join(
15
- [
16
- tag.span('Error: ', class: 'govuk-visually-hidden'),
17
- message
18
- ]
19
- )
15
+ content_tag('span', class: %(#{brand}-error-message), id: error_id) do
16
+ safe_join([error_prefix, error_message])
20
17
  end
21
18
  end
22
19
 
23
- def message
20
+ private
21
+
22
+ def error_prefix
23
+ tag.span('Error: ', class: %(#{brand}-visually-hidden))
24
+ end
25
+
26
+ def error_message
24
27
  @builder.object.errors.messages[@attribute_name]&.first
25
28
  end
26
29
  end
@@ -12,47 +12,44 @@ 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: ['govuk-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
- 'govuk-error-summary'.concat('__', part)
50
+ %(#{brand}-error-summary).concat('__', part)
54
51
  else
55
- 'govuk-error-summary'
52
+ %(#{brand}-error-summary)
56
53
  end
57
54
  end
58
55
 
@@ -68,12 +65,12 @@ 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',
75
72
  data: {
76
- module: 'govuk-error-summary'
73
+ module: %(#{brand}-error-summary)
77
74
  },
78
75
  aria: {
79
76
  labelledby: error_summary_title_id
@@ -1,44 +1,45 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class File < Base
4
+ using PrefixableArray
5
+
4
6
  include Traits::Error
5
7
  include Traits::Hint
6
8
  include Traits::Label
7
9
  include Traits::Supplemental
8
10
 
9
- 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)
10
12
  super(builder, object_name, attribute_name, &block)
11
13
 
12
- @label = label
13
- @hint_text = hint_text
14
- @extra_args = extra_args
14
+ @label = label
15
+ @caption = caption
16
+ @hint_text = hint_text
17
+ @extra_options = kwargs
15
18
  end
16
19
 
17
20
  def html
18
21
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
19
- safe_join(
20
- [
21
- label_element.html,
22
- supplemental_content.html,
23
- hint_element.html,
24
- error_element.html,
25
- @builder.file_field(
26
- @attribute_name,
27
- id: field_id(link_errors: true),
28
- class: file_classes,
29
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) },
30
- **@extra_args
31
- )
32
- ]
33
- )
22
+ safe_join([label_element, supplemental_content, hint_element, error_element, file])
34
23
  end
35
24
  end
36
25
 
37
26
  private
38
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
+
39
40
  def file_classes
40
- %w(govuk-file-upload).tap do |c|
41
- c.push('govuk-file-upload--error') if has_errors?
41
+ %w(file-upload).prefix(brand).tap do |c|
42
+ c.push(%(#{brand}-file-upload--error)) if has_errors?
42
43
  end
43
44
  end
44
45
  end
@@ -1,6 +1,8 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class Hint < Base
4
+ using PrefixableArray
5
+
4
6
  include Traits::Hint
5
7
  include Traits::Localisation
6
8
 
@@ -22,22 +24,19 @@ module GOVUKDesignSystemFormBuilder
22
24
  private
23
25
 
24
26
  def hint_text(supplied)
25
- [
26
- supplied.presence,
27
- localised_text(:hint)
28
- ].compact.first
27
+ [supplied.presence, localised_text(:hint)].compact.first
29
28
  end
30
29
 
31
30
  def hint_classes
32
- %w(govuk-hint).push(@radio_class, @checkbox_class).compact
31
+ %w(hint).prefix(brand).push(@radio_class, @checkbox_class).compact
33
32
  end
34
33
 
35
34
  def radio_class(radio)
36
- radio ? 'govuk-radios__hint' : nil
35
+ radio ? %(#{brand}-radios__hint) : nil
37
36
  end
38
37
 
39
38
  def checkbox_class(checkbox)
40
- checkbox ? 'govuk-checkboxes__hint' : nil
39
+ checkbox ? %(#{brand}-checkboxes__hint) : nil
41
40
  end
42
41
  end
43
42
  end
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Email < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Number < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Password < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Phone < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Text < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -2,6 +2,8 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class URL < Base
5
+ using PrefixableArray
6
+
5
7
  include Traits::Input
6
8
  include Traits::Error
7
9
  include Traits::Hint
@@ -1,40 +1,45 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class Label < Base
4
+ using PrefixableArray
5
+
6
+ include Traits::Caption
4
7
  include Traits::Localisation
5
8
 
6
- 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)
7
10
  super(builder, object_name, attribute_name)
8
11
 
9
- @value = value # used by field_id
10
- @text = label_text(text, hidden)
11
- @size_class = label_size_class(size)
12
- @radio_class = radio_class(radio)
13
- @checkbox_class = checkbox_class(checkbox)
14
- @tag = tag
15
- @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
16
26
  end
17
27
 
18
28
  def html
19
- return nil if @text.blank?
29
+ return nil if [@content, @text].all?(&:blank?)
20
30
 
21
31
  if @tag.present?
22
- content_tag(@tag, class: 'govuk-label-wrapper') { build_label }
32
+ content_tag(@tag, class: %(#{brand}-label-wrapper)) { label }
23
33
  else
24
- build_label
34
+ label
25
35
  end
26
36
  end
27
37
 
28
38
  private
29
39
 
30
- def build_label
31
- @builder.label(
32
- @attribute_name,
33
- value: @value,
34
- for: field_id(link_errors: @link_errors),
35
- class: %w(govuk-label).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
36
- ) do
37
- @text
40
+ def label
41
+ @builder.label(@attribute_name, label_options) do
42
+ @content || safe_join([caption_element.html, @text])
38
43
  end
39
44
  end
40
45
 
@@ -42,26 +47,34 @@ module GOVUKDesignSystemFormBuilder
42
47
  text = [option_text, localised_text(:label), @attribute_name.capitalize].compact.first.to_s
43
48
 
44
49
  if hidden
45
- tag.span(text, class: %w(govuk-visually-hidden))
50
+ tag.span(text, class: %w(visually-hidden).prefix(brand))
46
51
  else
47
52
  text
48
53
  end
49
54
  end
50
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
+
51
64
  def radio_class(radio)
52
- radio ? 'govuk-radios__label' : nil
65
+ radio ? %(#{brand}-radios__label) : nil
53
66
  end
54
67
 
55
68
  def checkbox_class(checkbox)
56
- checkbox ? 'govuk-checkboxes__label' : nil
69
+ checkbox ? %(#{brand}-checkboxes__label) : nil
57
70
  end
58
71
 
59
72
  def label_size_class(size)
60
73
  case size
61
- when 'xl' then "govuk-label--xl"
62
- when 'l' then "govuk-label--l"
63
- when 'm' then "govuk-label--m"
64
- when 's' then "govuk-label--s"
74
+ when 'xl' then %(#{brand}-label--xl)
75
+ when 'l' then %(#{brand}-label--l)
76
+ when 'm' then %(#{brand}-label--m)
77
+ when 's' then %(#{brand}-label--s)
65
78
  when nil then nil
66
79
  else
67
80
  fail "invalid size '#{size}', must be xl, l, m, s or nil"