govuk_design_system_formbuilder 1.1.11 → 1.2.1

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