ccs-frontend_helpers 0.1.2 → 0.3.0

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -3
  3. data/CHANGELOG.md +40 -0
  4. data/Gemfile +7 -6
  5. data/Gemfile.lock +121 -114
  6. data/README.md +12 -0
  7. data/lib/ccs/components/ccs/footer.rb +0 -1
  8. data/lib/ccs/components/ccs/header.rb +0 -1
  9. data/lib/ccs/components/govuk/accordion/section/content.rb +1 -1
  10. data/lib/ccs/components/govuk/accordion.rb +11 -0
  11. data/lib/ccs/components/govuk/button.rb +4 -1
  12. data/lib/ccs/components/govuk/cookie_banner/action.rb +1 -0
  13. data/lib/ccs/components/govuk/cookie_banner/message.rb +1 -1
  14. data/lib/ccs/components/govuk/details.rb +1 -1
  15. data/lib/ccs/components/govuk/error_message.rb +5 -2
  16. data/lib/ccs/components/govuk/exit_this_page.rb +79 -0
  17. data/lib/ccs/components/govuk/field/input/character_count/count_message.rb +62 -0
  18. data/lib/ccs/components/govuk/field/input/character_count.rb +55 -42
  19. data/lib/ccs/components/govuk/field/input/password_input/show_hide_button.rb +72 -0
  20. data/lib/ccs/components/govuk/field/input/password_input.rb +101 -0
  21. data/lib/ccs/components/govuk/field/input/select.rb +2 -2
  22. data/lib/ccs/components/govuk/field/input/text_input.rb +23 -7
  23. data/lib/ccs/components/govuk/field/input.rb +4 -0
  24. data/lib/ccs/components/govuk/field/inputs/checkboxes.rb +8 -28
  25. data/lib/ccs/components/govuk/field/inputs/date_input.rb +4 -25
  26. data/lib/ccs/components/govuk/field/inputs/item/checkbox.rb +1 -13
  27. data/lib/ccs/components/govuk/field/inputs/item/radio.rb +1 -13
  28. data/lib/ccs/components/govuk/field/inputs/item.rb +24 -10
  29. data/lib/ccs/components/govuk/field/inputs/radios.rb +7 -23
  30. data/lib/ccs/components/govuk/field/inputs.rb +31 -7
  31. data/lib/ccs/components/govuk/field.rb +12 -2
  32. data/lib/ccs/components/govuk/fieldset.rb +1 -1
  33. data/lib/ccs/components/govuk/footer/meta.rb +1 -1
  34. data/lib/ccs/components/govuk/footer.rb +1 -2
  35. data/lib/ccs/components/govuk/header/navigation.rb +4 -2
  36. data/lib/ccs/components/govuk/header.rb +26 -8
  37. data/lib/ccs/components/govuk/pagination/increment/next.rb +6 -3
  38. data/lib/ccs/components/govuk/pagination/increment/previous.rb +6 -3
  39. data/lib/ccs/components/govuk/pagination/increment.rb +11 -3
  40. data/lib/ccs/components/govuk/pagination/item.rb +1 -1
  41. data/lib/ccs/components/govuk/pagination.rb +2 -3
  42. data/lib/ccs/components/govuk/summary_list/action/link.rb +18 -3
  43. data/lib/ccs/components/govuk/summary_list/card/actions.rb +3 -2
  44. data/lib/ccs/components/govuk/summary_list/card.rb +1 -1
  45. data/lib/ccs/components/govuk/summary_list/row/actions.rb +3 -2
  46. data/lib/ccs/components/govuk/summary_list/row.rb +7 -2
  47. data/lib/ccs/components/govuk/summary_list.rb +1 -1
  48. data/lib/ccs/components/govuk/tabs.rb +5 -3
  49. data/lib/ccs/components/govuk/task_list/item/status.rb +64 -0
  50. data/lib/ccs/components/govuk/task_list/item/title.rb +54 -0
  51. data/lib/ccs/components/govuk/task_list/item.rb +75 -0
  52. data/lib/ccs/components/govuk/task_list.rb +52 -0
  53. data/lib/ccs/components/govuk/warning_text.rb +1 -1
  54. data/lib/ccs/frontend_helpers/govuk_frontend/character_count.rb +1 -1
  55. data/lib/ccs/frontend_helpers/govuk_frontend/error_message.rb +1 -1
  56. data/lib/ccs/frontend_helpers/govuk_frontend/exit_this_page.rb +28 -0
  57. data/lib/ccs/frontend_helpers/govuk_frontend/password_input.rb +28 -0
  58. data/lib/ccs/frontend_helpers/govuk_frontend/task_list.rb +28 -0
  59. data/lib/ccs/frontend_helpers/govuk_frontend.rb +6 -0
  60. data/lib/ccs/frontend_helpers/version.rb +1 -1
  61. data/package.json +10 -0
  62. data/yarn.lock +8 -0
  63. metadata +15 -2
@@ -0,0 +1,79 @@
1
+ require_relative '../base'
2
+ require_relative 'button'
3
+
4
+ module CCS
5
+ module Components
6
+ module GovUK
7
+ # = GOV.UK Exit this page
8
+ #
9
+ # This is used to generate the exit this page component from the
10
+ # {https://design-system.service.gov.uk/components/exit-this-page GDS - Components - Exit this page}
11
+ #
12
+ # @!attribute [r] text
13
+ # @return [String] Text for the exit this page
14
+ # @!attribute [r] redirect_url
15
+ # @return [String] The redirect_url for the exit this page
16
+
17
+ class ExitThisPage < Base
18
+ include ActionView::Context
19
+ include ActionView::Helpers
20
+
21
+ private
22
+
23
+ attr_reader :text, :redirect_url
24
+
25
+ public
26
+
27
+ # @param text [String] the text for the exit this page
28
+ # @param redirect_url [String] the href for the exit this page
29
+ # @param options [Hash] options that will be used in customising the HTML
30
+ #
31
+ # @option options [String] :classes additional CSS classes for the exit this page HTML
32
+ # @option options [String] :activated_text Text announced by screen readers when Exit this Page has been activated via the keyboard shortcut. Defaults to "Loading."
33
+ # @option options [String] :timed_out_text Text announced by screen readers when the keyboard shortcut has timed out without successful activation. Defaults to "Exit this page expired."
34
+ # @option options [String] :press_two_more_times_text Text announced by screen readers when the user must press Shift two more times to activate the button. Defaults to "Shift, press 2 more times to exit."
35
+ # @option options [String] :press_one_more_time_text Text announced by screen readers when the user must press Shift one more time to activate the button. Defaults to "Shift, press 1 more time to exit."
36
+ # @option options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
37
+
38
+ def initialize(text: nil, redirect_url: nil, **options)
39
+ super(**options)
40
+
41
+ @text = text || default_text
42
+ @redirect_url = redirect_url || 'https://www.bbc.co.uk/weather'
43
+
44
+ %i[activated timed_out press_two_more_times press_one_more_time].each do |data_attribute|
45
+ data_attribute_name = :"#{data_attribute}_text"
46
+ @options[:attributes][:data][:"i18n.#{data_attribute.to_s.gsub('_', '-')}"] = options[data_attribute_name] if options[data_attribute_name]
47
+ end
48
+ end
49
+
50
+ # Generates the HTML for the GOV.UK Exit this page component
51
+ #
52
+ # @return [ActiveSupport::SafeBuffer]
53
+
54
+ def render
55
+ tag.div(**options[:attributes]) do
56
+ Button.new(text: text, href: redirect_url, context: context, classes: 'govuk-button--warning govuk-exit-this-page__button govuk-js-exit-this-page-button', attributes: { rel: 'nofollow noreferrer' }).render
57
+ end
58
+ end
59
+
60
+ # The default attributes for the exit this page
61
+
62
+ DEFAULT_ATTRIBUTES = { class: 'govuk-exit-this-page', data: { module: 'govuk-exit-this-page' } }.freeze
63
+
64
+ private
65
+
66
+ # Generates the default HTML for the GOV.UK exit this page component
67
+ #
68
+ # @return [ActiveSupport::SafeBuffer]
69
+
70
+ def default_text
71
+ capture do
72
+ concat(tag.span('Emergency', class: 'govuk-visually-hidden'))
73
+ concat(' Exit this page')
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,62 @@
1
+ module CCS
2
+ module Components
3
+ module GovUK
4
+ class Field < Base
5
+ class Input < Field
6
+ class CharacterCount
7
+ # = GOV.UK Character count message
8
+ #
9
+ # This is used to generate the character count message
10
+ #
11
+ # @!attribute [r] count_message
12
+ # @return [Hint] Hint with the count message
13
+ # @!attribute [r] after_input
14
+ # @return [String] Text or HTML for after the textarea input
15
+
16
+ class CountMessage
17
+ include ActionView::Context
18
+ include ActionView::Helpers
19
+
20
+ private
21
+
22
+ attr_reader :count_message, :after_input
23
+
24
+ public
25
+
26
+ # @param character_count_attribute [String] the name of the field as it will appear in the textarea
27
+ # @param context [ActionView::Base] the view context
28
+ # @param character_count_options (see CCS::Components::GovUK::Field::Input::CharacterCount.get_character_count_from_group_options)
29
+ # @param after_input [String] Text or HTML that goes after the input
30
+ #
31
+ # @option (see CCS::Components::GovUK::Field::Input::CharacterCount.get_character_count_from_group_options)
32
+
33
+ def initialize(character_count_attribute:, context:, character_count_options:, after_input: nil)
34
+ count_message = character_count_options[:textarea_description] || {}
35
+
36
+ count_message_length = character_count_options[:maxwords] || character_count_options[:maxlength]
37
+ count_message_default = "You can enter up to %<count>s #{character_count_options[:maxwords] ? 'words' : 'characters'}"
38
+
39
+ text = count_message_length ? format(count_message[:count_message] || count_message_default, count: count_message_length) : ''
40
+ classes = "govuk-character-count__message #{count_message[:classes]}".rstrip
41
+
42
+ @count_message = Hint.new(text: text, classes: classes, attributes: { id: "#{character_count_attribute}-info" }, context: context)
43
+ @after_input = after_input
44
+ end
45
+
46
+ # Generates the HTML for the GOV.UK Character count message
47
+ #
48
+ # @return [ActiveSupport::SafeBuffer]
49
+
50
+ def render
51
+ capture do
52
+ concat(count_message.render)
53
+ concat(after_input) if after_input
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,5 +1,5 @@
1
1
  require_relative 'textarea'
2
- require_relative '../../hint'
2
+ require_relative 'character_count/count_message'
3
3
 
4
4
  module CCS
5
5
  module Components
@@ -15,18 +15,15 @@ module CCS
15
15
  #
16
16
  # @!attribute [r] textarea
17
17
  # @return [Textarea] The initialised textarea
18
- # @!attribute [r] fallback_hint
19
- # @return [Hint] The initialised character count fallback hint
18
+ # @!attribute [r] textarea_description
19
+ # @return [Hint] The initialised character count textarea description
20
20
  # @!attribute [r] character_count_html_options
21
21
  # @return [Hash] HTML options for the character count
22
22
 
23
23
  class CharacterCount
24
- include ActionView::Context
25
- include ActionView::Helpers
26
-
27
24
  private
28
25
 
29
- attr_reader :textarea, :fallback_hint, :character_count_html_options
26
+ attr_reader :textarea, :textarea_description
30
27
 
31
28
  public
32
29
 
@@ -38,24 +35,13 @@ module CCS
38
35
  #
39
36
  # @option (see initialise_character_count_html_options)
40
37
 
41
- def initialize(attribute:, character_count_options:, context:, **options)
38
+ def initialize(attribute:, context:, character_count_options: {}, **options)
42
39
  character_count_attribute = options[:form] ? "#{options[:form].object_name}_#{attribute}" : attribute
43
40
 
44
- initialise_textarea(attribute, character_count_attribute, context, options)
45
- initialise_character_count_html_options(character_count_options)
46
- initialise_fallback_hint(character_count_attribute, context, character_count_options)
41
+ initialise_textarea(attribute, character_count_attribute, character_count_options, context, options)
47
42
  end
48
43
 
49
- # Generates the HTML for the GOV.UK Character count component
50
- #
51
- # @return [ActiveSupport::SafeBuffer]
52
-
53
- def render
54
- tag.div(**character_count_html_options) do
55
- concat(textarea.render)
56
- concat(fallback_hint.render)
57
- end
58
- end
44
+ delegate :render, to: :textarea
59
45
 
60
46
  private
61
47
 
@@ -63,19 +49,23 @@ module CCS
63
49
  #
64
50
  # @param attribute [Symbol] the attribute of the field
65
51
  # @param character_count_attribute [String] the name of the field as it will appear in the textarea
52
+ # @param character_count_options [Hash] options for the character count
66
53
  # @param context [ActionView::Base] the view context
67
54
  # @param options [Hash] options that will be used for the textarea
68
55
  #
69
56
  # @option (see CCS::Components::GovUK::Field::Input::Textarea#initialize)
70
57
 
71
- def initialise_textarea(attribute, character_count_attribute, context, options)
58
+ def initialise_textarea(attribute, character_count_attribute, character_count_options, context, options)
59
+ set_character_count_from_group_options(character_count_options, options)
60
+
72
61
  ((options[:attributes] ||= {})[:aria] ||= {})[:describedby] = [options.dig(:attributes, :aria, :describedby), "#{character_count_attribute}-info"].compact.join(' ')
73
- options[:classes] = "#{options[:classes]} govuk-js-character-count".lstrip
62
+ options[:classes] = "govuk-js-character-count #{options[:classes]}".rstrip
74
63
 
75
- @textarea = Textarea.new(attribute: attribute, context: context, **options)
64
+ count_message = CountMessage.new(character_count_attribute: character_count_attribute, context: context, character_count_options: character_count_options, after_input: options.delete(:after_input))
65
+ @textarea = Textarea.new(attribute: attribute, context: context, after_input: count_message.render, **options)
76
66
  end
77
67
 
78
- # Initialises the charcter count options
68
+ # Sets the charcter count form group options
79
69
  #
80
70
  # @param character_count_options [Hash] options for the charcter count
81
71
  #
@@ -87,40 +77,63 @@ module CCS
87
77
  # If +maxwords+ is provided, the +maxlength+ option will be ignored.
88
78
  # @option character_count_options [String] :threshold the percentage value of the limit at which point the count message is displayed.
89
79
  # If this attribute is set, the count message will be hidden by default.
90
- # @option character_count_options [Hash] :fallback_hint ({}) additional parameters that will be used to create the hint containing the character count text:
80
+ # @option character_count_options [Hash] :textarea_description ({}) additional parameters that will be used to create the hint containing the character count text:
91
81
  # - +:count_message+ replaced the default text for the count message.
92
82
  # If you want the count number to appear, put %<count>s in the string and it will be replaced with the number
93
- # - +classes+ additional CSS classes for the fallback hint HTML
94
-
95
- def initialise_character_count_html_options(character_count_options)
96
- character_count_html_options = { class: 'govuk-character-count', data: { module: 'govuk-character-count' } }
83
+ # - +classes+ additional CSS classes for the textarea description HTML
84
+ # @option character_count_options [String] :characters_under_limit Message displayed when the number of characters is under the configured maximum, maxlength
85
+ # @option character_count_options [String] :characters_at_limit_text Message displayed when the number of characters reaches the configured maximum, maxlength
86
+ # @option character_count_options [String] :characters_over_limit Message displayed when the number of characters is over the configured maximum, maxlength
87
+ # @option character_count_options [String] :words_under_limit Message displayed when the number of words is under the configured maximum, maxwords
88
+ # @option character_count_options [String] :words_at_limit_text Message displayed when the number of words reaches the configured maximum, maxwords
89
+ # @option character_count_options [String] :words_over_limit Message displayed when the number of words is over the configured maximum, maxwords
90
+
91
+ def set_character_count_from_group_options(character_count_options, options)
92
+ (options[:form_group] ||= {})[:classes] = "govuk-character-count #{options.dig(:form_group, :classes)}".rstrip
93
+ ((options[:form_group][:attributes] ||= {})[:data] ||= {})[:module] = 'govuk-character-count'
97
94
 
98
95
  %i[maxlength threshold maxwords].each do |data_attribute|
99
- character_count_html_options[:data][data_attribute] = character_count_options[data_attribute].to_s if character_count_options[data_attribute]
96
+ options[:form_group][:attributes][:data][data_attribute] = character_count_options[data_attribute].to_s if character_count_options[data_attribute]
100
97
  end
101
98
 
102
- @character_count_html_options = character_count_html_options
99
+ get_chacrter_count_translations(character_count_options) do |data_attribute, value|
100
+ options[:form_group][:attributes][:data][data_attribute] = value
101
+ end
103
102
  end
104
103
 
105
- # Initialises the charcter count fall back hint
104
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
105
+
106
+ # Generator for the translation options for character count
106
107
  #
107
- # @param character_count_attribute [String] the name of the field as it will appear in the textarea
108
- # @param context [ActionView::Base] the view context
109
108
  # @param (see initialise_character_count_html_options)
110
109
  #
111
110
  # @option (see initialise_character_count_html_options)
111
+ #
112
+ # @return [Hash]
112
113
 
113
- def initialise_fallback_hint(character_count_attribute, context, character_count_options)
114
- fallback_hint = character_count_options[:fallback_hint] || {}
114
+ def get_chacrter_count_translations(character_count_options)
115
+ %i[characters_at_limit words_at_limit].each do |data_attribute|
116
+ data_attribute_name = :"#{data_attribute}_text"
115
117
 
116
- fallback_hint_length = character_count_options[:maxwords] || character_count_options[:maxlength]
117
- fallback_hint_default = "You can enter up to %<count>s #{character_count_options[:maxwords] ? 'words' : 'characters'}"
118
+ next unless character_count_options[data_attribute_name]
119
+
120
+ yield :"i18n.#{data_attribute.to_s.gsub('_', '-')}", character_count_options[data_attribute_name]
121
+ end
118
122
 
119
- text = format(fallback_hint[:count_message] || fallback_hint_default, count: fallback_hint_length)
120
- classes = "#{fallback_hint[:classes]} govuk-character-count__message".lstrip
123
+ %i[characters_under_limit characters_over_limit words_under_limit words_over_limit].each do |data_attribute|
124
+ next unless character_count_options[data_attribute]
121
125
 
122
- @fallback_hint = Hint.new(text: text, classes: classes, attributes: { id: "#{character_count_attribute}-info" }, context: context)
126
+ %i[other one].each do |plural_rule|
127
+ next unless character_count_options[data_attribute][plural_rule]
128
+
129
+ yield :"i18n.#{data_attribute.to_s.gsub('_', '-')}.#{plural_rule}", character_count_options[data_attribute][plural_rule]
130
+ end
131
+ end
132
+
133
+ yield :'i18n.textarea-description.other', character_count_options[:textarea_description][:count_message] if character_count_options.dig(:textarea_description, :count_message) && !(character_count_options[:maxwords] || character_count_options[:maxlength])
123
134
  end
135
+
136
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
124
137
  end
125
138
  end
126
139
  end
@@ -0,0 +1,72 @@
1
+ require_relative '../../../button'
2
+
3
+ module CCS
4
+ module Components
5
+ module GovUK
6
+ class Field < Base
7
+ class Input < Field
8
+ class PasswordInput
9
+ # = GOV.UK Password input show/hide button
10
+ #
11
+ # This is used to generate the password input show/hide button
12
+ #
13
+ # @!attribute [r] show_hide_button
14
+ # @return [Button] Show/Hide button
15
+ # @!attribute [r] after_input
16
+ # @return [String] Text or HTML for after the textarea input
17
+
18
+ class ShowHideButton
19
+ include ActionView::Context
20
+ include ActionView::Helpers
21
+ include ActionView::Helpers::FormTagHelper
22
+
23
+ private
24
+
25
+ attr_reader :show_hide_button, :after_input
26
+
27
+ public
28
+
29
+ # @param attribute [String] the name of the field as it will appear in the input
30
+ # @param context [ActionView::Base] the view context
31
+ # @param button [Hash] options for the button
32
+ # @param after_input [String] Text or HTML that goes after the input
33
+ #
34
+ # @option button [String] :classes classes to add to the button
35
+ #
36
+ # @option (see CCS::Components::GovUK::Field::Input::PasswordInput.set_password_input_from_group_options)
37
+
38
+ def initialize(attribute:, context:, button: {}, after_input: nil, **options)
39
+ button[:classes] = "govuk-button--secondary govuk-password-input__toggle govuk-js-password-input-toggle #{button[:classes]}".rstrip
40
+ button[:attributes] = {
41
+ type: :button,
42
+ aria: {
43
+ controls: options.dig(:attributes, :id) || field_id(options[:form]&.object_name, attribute),
44
+ label: options[:show_password_aria_label_text] || 'Show password'
45
+ },
46
+ hidden: {
47
+ value: true,
48
+ optional: true
49
+ }
50
+ }
51
+
52
+ @show_hide_button = Button.new(text: options[:show_password_text] || 'Show', context: context, classes: button[:classes], attributes: button[:attributes])
53
+ @after_input = after_input
54
+ end
55
+
56
+ # Generates the HTML for the GOV.UK Password input show/hide button
57
+ #
58
+ # @return [ActiveSupport::SafeBuffer]
59
+
60
+ def render
61
+ capture do
62
+ concat(show_hide_button.render)
63
+ concat(after_input) if after_input
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,101 @@
1
+ require_relative 'text_input'
2
+ require_relative 'password_input/show_hide_button'
3
+
4
+ module CCS
5
+ module Components
6
+ module GovUK
7
+ class Field < Base
8
+ class Input < Field
9
+ # = GOV.UK Password input
10
+ #
11
+ # This is used for generating the password input component from the
12
+ # {https://design-system.service.gov.uk/components/password-input GDS - Components - Password Input}
13
+ #
14
+ # @!attribute [r] text_input
15
+ # @return [CCS::Components::GovUK::Field::Input::TextInput] Initialised text input component
16
+
17
+ class PasswordInput
18
+ private
19
+
20
+ attr_reader :text_input
21
+
22
+ public
23
+
24
+ # @param (see CCS::Components::GovUK::Field::Input::TextInput#initialize)
25
+ #
26
+ # @option (see CCS::Components::GovUK::Field::Input::TextInput#initialize)
27
+
28
+ def initialize(attribute:, context:, **options)
29
+ set_password_input_from_group_options(options)
30
+
31
+ show_hide_button = ShowHideButton.new(attribute: attribute, context: context, after_input: options.delete(:after_input), **options)
32
+
33
+ options[:attributes] ||= {}
34
+ options[:attributes][:spellcheck] = false
35
+ options[:attributes][:autocapitalize] = 'none'
36
+ options[:attributes][:autocomplete] ||= 'current-password'
37
+
38
+ @text_input = TextInput.new(
39
+ context: context,
40
+ attribute: attribute,
41
+ after_input: show_hide_button.render,
42
+ input_wrapper: {
43
+ classes: 'govuk-password-input__wrapper'
44
+ },
45
+ classes: "govuk-password-input__input govuk-js-password-input-input #{options.delete(:classes)}".rstrip,
46
+ field_type: :password,
47
+ **options
48
+ )
49
+ end
50
+
51
+ delegate :render, to: :text_input
52
+
53
+ private
54
+
55
+ # rubocop:disable Naming/AccessorMethodName
56
+
57
+ # Sets the password input form group options
58
+ #
59
+ # @param options [Hash] options for the password input
60
+ #
61
+ # @option options [String] :show_password_text button text when the password is hidden
62
+ # @option options [String] :hide_password_text button text when the password is visible
63
+ # @option options [String] :show_password_aria_label_text button text exposed to assistive technologies, like screen readers, when the password is hidden
64
+ # @option options [String] :hide_password_aria_label_text button text exposed to assistive technologies, like screen readers, when the password is visible
65
+ # @option options [String] :password_shown_announcement_text announcement made to screen reader users when their password has become visible in plain text
66
+ # @option options [String] :password_hidden_announcement_text announcement made to screen reader users when their password has been obscured and is not visible
67
+
68
+ def set_password_input_from_group_options(options)
69
+ (options[:form_group] ||= {})[:classes] = "govuk-password-input #{options.dig(:form_group, :classes)}".rstrip
70
+ ((options[:form_group][:attributes] ||= {})[:data] ||= {})[:module] = 'govuk-password-input'
71
+
72
+ get_password_input_translations(options) do |data_attribute, value|
73
+ options[:form_group][:attributes][:data][data_attribute] = value
74
+ end
75
+ end
76
+
77
+ # rubocop:enable Naming/AccessorMethodName
78
+
79
+ # Generator for the translation options for password input
80
+ #
81
+ # @param (see initialise_password_input_html_options)
82
+ #
83
+ # @option (see initialise_password_input_html_options)
84
+ #
85
+ # @yield Data attribute key and the value
86
+
87
+ def get_password_input_translations(password_input_options)
88
+ %i[show_password hide_password show_password_aria_label hide_password_aria_label password_shown_announcement password_hidden_announcement].each do |data_attribute|
89
+ data_attribute_name = :"#{data_attribute}_text"
90
+
91
+ next unless password_input_options[data_attribute_name]
92
+
93
+ yield :"i18n.#{data_attribute.to_s.gsub('_', '-')}", password_input_options[data_attribute_name]
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -38,8 +38,8 @@ module CCS
38
38
  @items = items.map do |item|
39
39
  [
40
40
  item[:text] || item[:value],
41
- item[:value],
42
- (item[:attributes] || {})
41
+ item[:value].nil? ? item[:text] : item[:value],
42
+ item[:attributes] || {}
43
43
  ]
44
44
  end
45
45
  @selected = @options[:model] ? @options[:model].send(attribute) : selected
@@ -19,11 +19,13 @@ module CCS
19
19
  # @return [Fix] The initialised prefix
20
20
  # @!attribute [r] suffix
21
21
  # @return [Fix] The initialised suffix
22
+ # @!attribute [r] input_wrapper_html_options
23
+ # @return [Fix] HTML options for the input wrapper
22
24
 
23
25
  class TextInput < Input
24
26
  private
25
27
 
26
- attr_reader :field_type, :value, :prefix, :suffix
28
+ attr_reader :field_type, :value, :prefix, :suffix, :input_wrapper_html_options
27
29
 
28
30
  public
29
31
 
@@ -36,33 +38,41 @@ module CCS
36
38
  # see {CCS::Components::GovUK::Field::Input::TextInput::Fix#initialize Fix#initialize} for more details.
37
39
  # @param suffix [Hash] optional suffix for the input field,
38
40
  # see {CCS::Components::GovUK::Field::Input::TextInput::Fix#initialize Fix#initialize} for more details.
41
+ # @param input_wrapper [Hash] HTML options for the input wrapper
39
42
  #
40
43
  # @option (see CCS::Components::GovUK::Field::Input#initialize)
41
44
 
42
- def initialize(attribute:, field_type: :text, value: nil, prefix: nil, suffix: nil, **options)
45
+ def initialize(attribute:, field_type: :text, value: nil, prefix: nil, suffix: nil, input_wrapper: {}, **options)
43
46
  super(attribute: attribute, **options)
44
47
 
45
48
  @field_type = :"#{field_type}_field"
46
49
  @value = @options[:model] ? @options[:model].send(attribute) : value
47
50
  @prefix = Fix.new(fix: 'pre', context: @context, **prefix) if prefix
48
51
  @suffix = Fix.new(fix: 'suf', context: @context, **suffix) if suffix
52
+ @input_wrapper_html_options = {
53
+ class: "govuk-input__wrapper #{input_wrapper[:classes]}".rstrip
54
+ }.merge(input_wrapper[:attributes] || {})
49
55
  end
50
56
 
51
57
  # rubocop:enable Metrics/ParameterLists
58
+ # rubocop:disable Metrics/AbcSize
52
59
 
53
60
  # Generates the HTML for the GOV.UK Text Input component
54
61
  #
55
62
  # @return [ActiveSupport::SafeBuffer]
56
63
 
57
64
  def render
58
- super() do
59
- text_input_wrapper do
65
+ form_group.render do |display_error_message|
66
+ concat(label.render)
67
+ concat(hint.render) if hint
68
+ concat(display_error_message)
69
+ concat(text_input_wrapper do
60
70
  if options[:form]
61
71
  options[:form].send(field_type, attribute, **options[:attributes])
62
72
  else
63
73
  context.send("#{field_type}_tag", attribute, value, **options[:attributes])
64
74
  end
65
- end
75
+ end)
66
76
  end
67
77
  end
68
78
 
@@ -72,6 +82,8 @@ module CCS
72
82
 
73
83
  private
74
84
 
85
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
86
+
75
87
  # Wrapper method used by {render} to wrap the text input with a prefix or suffix if they exist
76
88
  #
77
89
  # @yield the text input HTML
@@ -79,16 +91,20 @@ module CCS
79
91
  # @return [ActiveSupport::SafeBuffer]
80
92
 
81
93
  def text_input_wrapper
82
- if prefix || suffix
83
- tag.div(class: 'govuk-input__wrapper') do
94
+ if prefix || suffix || before_input || after_input
95
+ tag.div(**input_wrapper_html_options) do
96
+ concat(before_input) if before_input
84
97
  concat(prefix.render) if prefix
85
98
  concat(yield)
86
99
  concat(suffix.render) if suffix
100
+ concat(after_input) if after_input
87
101
  end
88
102
  else
89
103
  yield
90
104
  end
91
105
  end
106
+
107
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
92
108
  end
93
109
  end
94
110
  end
@@ -25,6 +25,8 @@ module CCS
25
25
 
26
26
  # @param (see CCS::Components::GovUK::Field#initialize)
27
27
  # @param label [Hash] attributes for the label, see {CCS::Components::GovUK::Label#initialize Label#initialize} for more details.
28
+ # @param before_input [String] text or HTML to go before the input
29
+ # @param after_input [String] text or HTML to go after the input
28
30
  #
29
31
  # @option (see CCS::Components::GovUK::Field#initialize)
30
32
 
@@ -52,7 +54,9 @@ module CCS
52
54
  concat(label.render)
53
55
  concat(hint.render) if hint
54
56
  concat(display_error_message)
57
+ concat(before_input) if before_input
55
58
  concat(yield)
59
+ concat(after_input) if after_input
56
60
  end
57
61
  end
58
62
  end
@@ -12,18 +12,9 @@ module CCS
12
12
  #
13
13
  # This is used for generating the checkboxes component from the
14
14
  # {https://design-system.service.gov.uk/components/checkboxes GDS - Components - Checkboxes}
15
- #
16
- # @!attribute [r] checkbox_items
17
- # @return [Array<Item::Divider|Item::Checkbox|Item::Checkbox>] An array of the initialised checkbox items
18
15
 
19
16
  class Checkboxes < Inputs
20
- private
21
-
22
- attr_reader :checkbox_items
23
-
24
- public
25
-
26
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
17
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
27
18
 
28
19
  # @param (see CCS::Components::GovUK::Field::Inputs#initialize)
29
20
  # @param checkbox_items [Array<Hash>] an array of options for the checkboxes.
@@ -34,29 +25,18 @@ module CCS
34
25
  def initialize(attribute:, checkbox_items:, **options)
35
26
  super(attribute: attribute, **options)
36
27
 
37
- if @options[:model] || @options[:form]
38
- values = (@options[:model] || @options[:form].object).send(attribute) || []
39
- checkbox_items.each { |checkbox_item| checkbox_item[:checked] = values.include?(checkbox_item[:value]) }
40
- end
28
+ @options[:values] ||= []
29
+ @options[:values] = (@options[:model] || @options[:form].object).send(attribute) || [] if @options[:model] || @options[:form]
30
+
31
+ checkbox_items.each { |checkbox_item| checkbox_item[:checked] = @options[:values].include?(checkbox_item[:value]) } if @options[:values].any?
32
+ checkbox_items.each { |checkbox_item| set_described_by(checkbox_item, @attribute, @error_message, @hint&.send(:options)) } unless @fieldset
41
33
 
42
34
  checkbox_item_class = @options[:form] ? Item::Checkbox::Form : Inputs::Item::Checkbox::Tag
43
35
 
44
- @checkbox_items = checkbox_items.map { |checkbox_item| checkbox_item[:divider] ? Item::Divider.new(divider: checkbox_item[:divider], type: 'checkboxes') : checkbox_item_class.new(attribute: attribute, form: @options[:form], context: @context, **checkbox_item) }
36
+ @input_items = checkbox_items.map { |checkbox_item| checkbox_item[:divider] ? Item::Divider.new(divider: checkbox_item[:divider], type: 'checkboxes') : checkbox_item_class.new(attribute: attribute, form: @options[:form], context: @context, **checkbox_item) }
45
37
  end
46
38
 
47
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
48
-
49
- # Generates the HTML for the GOV.UK Checkboxes component
50
- #
51
- # @return [ActiveSupport::SafeBuffer]
52
-
53
- def render
54
- super() do
55
- tag.div(**options[:attributes]) do
56
- checkbox_items.each { |checkbox_item| concat(checkbox_item.render) }
57
- end
58
- end
59
- end
39
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
60
40
 
61
41
  # The default attributes for the checkboxes
62
42