ccs-frontend_helpers 0.1.0.rc.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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +127 -0
  4. data/CHANGELOG.md +44 -0
  5. data/Gemfile +10 -0
  6. data/Gemfile.lock +241 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +102 -0
  9. data/Rakefile +10 -0
  10. data/ccs-frontend_helpers.gemspec +47 -0
  11. data/lib/ccs/frontend_helpers/ccs_frontend/dashboard_panels.rb +79 -0
  12. data/lib/ccs/frontend_helpers/ccs_frontend/footer.rb +141 -0
  13. data/lib/ccs/frontend_helpers/ccs_frontend/header.rb +205 -0
  14. data/lib/ccs/frontend_helpers/ccs_frontend/logo.rb +49 -0
  15. data/lib/ccs/frontend_helpers/ccs_frontend.rb +20 -0
  16. data/lib/ccs/frontend_helpers/govuk_frontend/accordion.rb +115 -0
  17. data/lib/ccs/frontend_helpers/govuk_frontend/back_link.rb +39 -0
  18. data/lib/ccs/frontend_helpers/govuk_frontend/breadcrumbs.rb +76 -0
  19. data/lib/ccs/frontend_helpers/govuk_frontend/button.rb +127 -0
  20. data/lib/ccs/frontend_helpers/govuk_frontend/cookie_banner.rb +136 -0
  21. data/lib/ccs/frontend_helpers/govuk_frontend/details.rb +46 -0
  22. data/lib/ccs/frontend_helpers/govuk_frontend/error_message.rb +67 -0
  23. data/lib/ccs/frontend_helpers/govuk_frontend/error_summary.rb +100 -0
  24. data/lib/ccs/frontend_helpers/govuk_frontend/field/character_count.rb +165 -0
  25. data/lib/ccs/frontend_helpers/govuk_frontend/field/checkboxes.rb +200 -0
  26. data/lib/ccs/frontend_helpers/govuk_frontend/field/date_input.rb +153 -0
  27. data/lib/ccs/frontend_helpers/govuk_frontend/field/file_upload.rb +83 -0
  28. data/lib/ccs/frontend_helpers/govuk_frontend/field/input.rb +153 -0
  29. data/lib/ccs/frontend_helpers/govuk_frontend/field/radios.rb +201 -0
  30. data/lib/ccs/frontend_helpers/govuk_frontend/field/select.rb +124 -0
  31. data/lib/ccs/frontend_helpers/govuk_frontend/field/textarea.rb +106 -0
  32. data/lib/ccs/frontend_helpers/govuk_frontend/field.rb +213 -0
  33. data/lib/ccs/frontend_helpers/govuk_frontend/fieldset.rb +71 -0
  34. data/lib/ccs/frontend_helpers/govuk_frontend/footer.rb +183 -0
  35. data/lib/ccs/frontend_helpers/govuk_frontend/form_group.rb +50 -0
  36. data/lib/ccs/frontend_helpers/govuk_frontend/header.rb +161 -0
  37. data/lib/ccs/frontend_helpers/govuk_frontend/hint.rb +38 -0
  38. data/lib/ccs/frontend_helpers/govuk_frontend/inset_text.rb +44 -0
  39. data/lib/ccs/frontend_helpers/govuk_frontend/label.rb +92 -0
  40. data/lib/ccs/frontend_helpers/govuk_frontend/notification_banner.rb +136 -0
  41. data/lib/ccs/frontend_helpers/govuk_frontend/pagination.rb +336 -0
  42. data/lib/ccs/frontend_helpers/govuk_frontend/panel.rb +51 -0
  43. data/lib/ccs/frontend_helpers/govuk_frontend/phase_banner.rb +49 -0
  44. data/lib/ccs/frontend_helpers/govuk_frontend/skip_link.rb +40 -0
  45. data/lib/ccs/frontend_helpers/govuk_frontend/step_by_step_navigation.rb +215 -0
  46. data/lib/ccs/frontend_helpers/govuk_frontend/summary_list.rb +226 -0
  47. data/lib/ccs/frontend_helpers/govuk_frontend/table.rb +124 -0
  48. data/lib/ccs/frontend_helpers/govuk_frontend/tabs.rb +95 -0
  49. data/lib/ccs/frontend_helpers/govuk_frontend/tag.rb +42 -0
  50. data/lib/ccs/frontend_helpers/govuk_frontend/warning_text.rb +53 -0
  51. data/lib/ccs/frontend_helpers/govuk_frontend.rb +82 -0
  52. data/lib/ccs/frontend_helpers/shared_methods.rb +27 -0
  53. data/lib/ccs/frontend_helpers/version.rb +7 -0
  54. data/lib/ccs/frontend_helpers.rb +20 -0
  55. data/sig/ccs/frontend_helpers.rbs +6 -0
  56. metadata +241 -0
@@ -0,0 +1,215 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_view'
4
+
5
+ require_relative '../shared_methods'
6
+
7
+ module CCS
8
+ module FrontendHelpers
9
+ module GovUKFrontend
10
+ # = GOV.UK Step by step navigation
11
+ #
12
+ # This helper is used for generating the Step by step navigation component from the
13
+ # {https://design-system.service.gov.uk/patterns/step-by-step-navigation/ GDS - Pages - Step by step navigation}
14
+ #
15
+ # To use this component you need the following from {https://github.com/alphagov/govuk_publishing_components GOV.UK Publishing Components}.
16
+ # For the SCSS components you should add:
17
+ # - {https://github.com/alphagov/govuk_publishing_components/blob/main/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav.scss _step-by-step-nav.scss}
18
+ # - {https://github.com/alphagov/govuk_publishing_components/blob/main/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-related.scss _step-by-step-nav-related.scss}
19
+ # - {https://github.com/alphagov/govuk_publishing_components/blob/main/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-header.scss _step-by-step-nav-header.scss}
20
+ # For the JavaScript you should add:
21
+ # - {https://github.com/alphagov/govuk_publishing_components/blob/main/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js step-by-step-nav.js}
22
+
23
+ module StepByStepNavigation
24
+ include SharedMethods
25
+ include ActionView::Helpers
26
+ include ActionView::Context
27
+
28
+ # Generates the HTML for the GOV.UK Step by step navigation component (experimental)
29
+ #
30
+ # @param step_by_step_sections [Array] the navigation items that will be rendered to the page.
31
+ # See {govuk_step_by_step_navigation_section} for more details
32
+ # @param govuk_step_by_step_navigation_options [Hash] options that will be used in customising the HTML
33
+ #
34
+ # @option govuk_step_by_step_navigation_options [String] :classes additional CSS classes for the step by step navigation HTML
35
+ # @option govuk_step_by_step_navigation_options [Hash] :attributes ({data: { module: 'govuk-step-by-step-navigation', 'show-text': 'Show', 'hide-text': 'Hide', 'show-all-text': 'Show all', 'hide-all-text': 'Hide all' } })
36
+ # any additional attributes that will added as part of the HTML
37
+ #
38
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Step by step navigation
39
+ # which can then be rendered on the page
40
+
41
+ def govuk_step_by_step_navigation(step_by_step_sections, **govuk_step_by_step_navigation_options)
42
+ initialise_attributes_and_set_classes(govuk_step_by_step_navigation_options, 'gem-c-step-nav gem-c-step-nav--large gem-c-step-nav--active')
43
+ determine_step_by_step_navigation_attributes(govuk_step_by_step_navigation_options)
44
+
45
+ tag.div(**govuk_step_by_step_navigation_options[:attributes]) do
46
+ tag.ol(class: 'gem-c-step-nav__steps') do
47
+ step_by_step_sections.each.with_index(1) { |step_by_step_section, section_index| concat(govuk_step_by_step_navigation_section(step_by_step_section, section_index.to_s)) }
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # The HTML for a section within GOV.UK Step by step navigation, used by {govuk_step_by_step_navigation}
55
+ #
56
+ # @param step_by_step_section [Hash] the parameters that will be used to create the section
57
+ # @param section_index [String] the index of the section
58
+ #
59
+ # @option step_by_step_section [Hash] :heading the paramaters for the section heading,
60
+ # see {govuk_step_by_step_navigation_heading} for more details
61
+ # @option step_by_step_section [Array] :content the paramaters for the section content,
62
+ # see {govuk_step_by_step_navigation_content} for more details
63
+ #
64
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Step by step navigation section
65
+ # which is used in {govuk_step_by_step_navigation}
66
+
67
+ def govuk_step_by_step_navigation_section(step_by_step_section, section_index)
68
+ section_id = convert_to_id(step_by_step_section[:heading][:text])
69
+
70
+ tag.li(class: 'gem-c-step-nav__step js-step', id: section_id) do
71
+ concat(govuk_step_by_step_navigation_heading(step_by_step_section[:heading], section_index))
72
+ concat(govuk_step_by_step_navigation_content(step_by_step_section[:content], section_id, section_index))
73
+ end
74
+ end
75
+
76
+ # The HTML for a section heading within GOV.UK Step by step navigation, used by {govuk_step_by_step_navigation_section}
77
+ #
78
+ # @param section_heading [Hash] the parameters that will be used to create the heading
79
+ # @param section_index [String] the index of the section
80
+ #
81
+ # @option section_heading [Hash] :text text for the section heading
82
+ # @option section_heading [Hash] :logic (nil) text to show instead of a number in the sidebar
83
+ #
84
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Step by step navigation section heading
85
+ # which is used in {govuk_step_by_step_navigation_section}
86
+
87
+ def govuk_step_by_step_navigation_heading(section_heading, section_index)
88
+ logic = section_heading[:logic]
89
+
90
+ tag.div(class: 'gem-c-step-nav__header js-toggle-panel', data: { position: section_index }) do
91
+ tag.h2(class: 'gem-c-step-nav__title') do
92
+ concat(tag.span(class: "gem-c-step-nav__circle gem-c-step-nav__circle--#{logic ? 'logic' : 'number'}") do
93
+ tag.span(class: 'gem-c-step-nav__circle-inner') do
94
+ tag.span(class: 'gem-c-step-nav__circle-background') do
95
+ concat(tag.span('Step', class: 'govuk-visually-hidden'))
96
+ concat(logic || section_index)
97
+ end
98
+ end
99
+ end)
100
+ concat(tag.span(class: 'js-step-title') do
101
+ tag.span(section_heading[:text], class: 'js-step-title-text')
102
+ end)
103
+ end
104
+ end
105
+ end
106
+
107
+ # The HTML for a section content within GOV.UK Step by step navigation, used by {govuk_step_by_step_navigation_section}
108
+ #
109
+ # @param content [Array] an array of the content items that will be rendered within the section.
110
+ # Only two types of content are allowed:
111
+ # - +:paragraph+ - see {govuk_step_by_step_navigation_paragraph}
112
+ # - +:list+ - see {govuk_step_by_step_navigation_list}
113
+ # @param section_id [String] the id of the section
114
+ # @param section_index [String] the index of the section
115
+ #
116
+ # @option content [Symbol] :type the type of content, either +:paragraph+ or +list+
117
+ # @option content [Symbol] :text the text for the paragraph. Ignored unless the +type+ is +:list+
118
+ # @option content [Symbol] :items the items for the list. Ignored unless the +type+ is +:paragraph+
119
+ #
120
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Step by step navigation section content
121
+ # which is used in {govuk_step_by_step_navigation_section}
122
+
123
+ def govuk_step_by_step_navigation_content(content, section_id, section_index)
124
+ tag.div(class: 'gem-c-step-nav__panel js-panel', id: "step-panel-#{section_id}-#{section_index}") do
125
+ content.each do |element|
126
+ concat(
127
+ case element[:type]
128
+ when :paragraph
129
+ govuk_step_by_step_navigation_paragraph(element[:text])
130
+ when :list
131
+ govuk_step_by_step_navigation_list(element[:items])
132
+ end
133
+ )
134
+ end
135
+ end
136
+ end
137
+
138
+ # The HTML for the paragraph item within the GOV.UK Step by step navigation content, used by {govuk_step_by_step_navigation_content}
139
+ #
140
+ # @param text [String] the text for the paragraph
141
+ #
142
+ # @return [ActiveSupport::SafeBuffer] the HTML for the paragraph
143
+ # which is used in {govuk_step_by_step_navigation_content}
144
+
145
+ def govuk_step_by_step_navigation_paragraph(text)
146
+ tag.p(
147
+ text,
148
+ class: 'gem-c-step-nav__paragraph',
149
+ )
150
+ end
151
+
152
+ # The HTML for the list items within the GOV.UK Step by step navigation content, used by {govuk_step_by_step_navigation_content}
153
+ #
154
+ # @param items [Array] an array of the list items,
155
+ # see {govuk_step_by_step_navigation_list_item} for more details
156
+ #
157
+ # @return [ActiveSupport::SafeBuffer] the HTML for the list
158
+ # which is used in {govuk_step_by_step_navigation_content}
159
+
160
+ def govuk_step_by_step_navigation_list(items)
161
+ tag.ul(class: 'gem-c-step-nav__list gem-c-step-nav__list--choice', data: { length: items.length.to_s }) do
162
+ items.each do |item|
163
+ concat(govuk_step_by_step_navigation_list_item(item[:text], item[:no_marker]))
164
+ end
165
+ end
166
+ end
167
+
168
+ # The HTML for a list item, used by {govuk_step_by_step_navigation_list}
169
+ #
170
+ # @param text [Symbol] the text of the list item
171
+ # @param no_marker [Symbol] (nil) switch to hide the bullet marker
172
+ #
173
+ # @return [ActiveSupport::SafeBuffer] the HTML for the list item
174
+ # which is used in {govuk_step_by_step_navigation_list}
175
+
176
+ def govuk_step_by_step_navigation_list_item(text, no_marker)
177
+ list_item_classes = ['gem-c-step-nav__list-item js-list-item']
178
+ list_item_classes << 'gem-c-step-nav__list--no-marker' if no_marker
179
+
180
+ tag.li(class: list_item_classes) do
181
+ tag.span(text)
182
+ end
183
+ end
184
+
185
+ # Converts the title text into a string to be used as the section id
186
+ #
187
+ # @param title [String] the section title that will be converted
188
+ #
189
+ # @return [String] the section id
190
+
191
+ def convert_to_id(title)
192
+ title.downcase.gsub(' ', '-').gsub('(', '').gsub(')', '')
193
+ end
194
+
195
+ # Generates a hash with the attributes used in {govuk_step_by_step_navigation}
196
+ #
197
+ # @param govuk_step_by_step_navigation_options [Hash] options that will be used in customising the HTML
198
+ #
199
+ # @option (see govuk_step_by_step_navigation)
200
+ #
201
+ # @return [Hash] contains the HTMl attributes used in {govuk_step_by_step_navigation}
202
+
203
+ def determine_step_by_step_navigation_attributes(govuk_step_by_step_navigation_options)
204
+ set_data_module(govuk_step_by_step_navigation_options, 'govuk-step-by-step-navigation')
205
+
206
+ DEFAULT_SHOW_HIDE_TEXT.each { |key, value| govuk_step_by_step_navigation_options[:attributes][:data][key] ||= value }
207
+ end
208
+
209
+ # Default text for the show and hide buttons which are part of each section
210
+
211
+ DEFAULT_SHOW_HIDE_TEXT = { 'show-text': 'Show', 'hide-text': 'Hide', 'show-all-text': 'Show all', 'hide-all-text': 'Hide all' }.freeze
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_view'
4
+
5
+ require_relative '../shared_methods'
6
+
7
+ module CCS
8
+ module FrontendHelpers
9
+ module GovUKFrontend
10
+ # = GOV.UK Summary list
11
+ #
12
+ # This helper is used for generating the summary list component from the
13
+ # {https://design-system.service.gov.uk/components/summary-list GDS - Components - Summary list}
14
+
15
+ module SummaryList
16
+ include SharedMethods
17
+ include ActionView::Context
18
+ include ActionView::Helpers::TagHelper
19
+ include ActionView::Helpers::TextHelper
20
+ include ActionView::Helpers::UrlHelper
21
+
22
+ # Generates the HTML for the GOV.UK Summary list component
23
+ #
24
+ # @param summary_list_items [Array] the list of summary items. See {govuk_summary_list_row}
25
+ # @param govuk_summary_list_options [Hash] options that will be used in customising the HTML
26
+ #
27
+ # @option govuk_summary_list_options [String] :classes additional CSS classes for the summary list HTML
28
+ # @option govuk_summary_list_options [Hash] :attributes ({}) any additional attributes that will be added as part of the HTML
29
+ #
30
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Summary list
31
+ # which can then be rendered on the page
32
+
33
+ def govuk_summary_list(summary_list_items, **govuk_summary_list_options)
34
+ if govuk_summary_list_options[:card]
35
+ govuk_summary_card(**govuk_summary_list_options[:card]) do
36
+ _govuk_summary_list(summary_list_items, govuk_summary_list_options)
37
+ end
38
+ else
39
+ _govuk_summary_list(summary_list_items, govuk_summary_list_options)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ # Generates the HTML for the GOV.UK Summary list.
46
+ # Used in {govuk_summary_list} to gererate the actual summary list.
47
+ #
48
+ # @param (see govuk_summary_list)
49
+ #
50
+ # @option (see govuk_summary_list)
51
+ #
52
+ # @return (see govuk_summary_list)
53
+
54
+ def _govuk_summary_list(summary_list_items, govuk_summary_list_options)
55
+ initialise_attributes_and_set_classes(govuk_summary_list_options, 'govuk-summary-list')
56
+
57
+ any_row_has_actions = summary_list_items.any? { |summary_list_item| summary_list_item.dig(:actions, :items).present? }
58
+
59
+ tag.dl(**govuk_summary_list_options[:attributes]) do
60
+ summary_list_items.each do |summary_list_item|
61
+ concat(govuk_summary_list_row(summary_list_item, any_row_has_actions))
62
+ end
63
+ end
64
+ end
65
+
66
+ # rubocop:disable Metrics/AbcSize
67
+
68
+ # Generates the HTML for a summary list row used in {govuk_summary_list}
69
+ #
70
+ # @param summary_list_item [Hash] the list of summary items
71
+ # @param any_row_has_actions [Boolean] flag to indicate if any rows have actioms
72
+ #
73
+ # @option summary_list_item [String] :classes additional CSS classes for the summary row HTML
74
+ # @option summary_list_item [Hash] :key the key for the summary list.
75
+ # Has the following options:
76
+ # - +:text+ - the text for the key
77
+ # - +:classes+ - additional classes for the key
78
+ # @option summary_list_item [Hash] :value the value for the summary list.
79
+ # Has the following options:
80
+ # - +:text+ - the text for the value
81
+ # - +:classes+ - additional classes for the value
82
+ # @option summary_list_item [Hash] :actions the actions for the summary list.
83
+ # Has the following options:
84
+ # - +:items+ - the action items (see {govuk_summary_list_action_link})
85
+ # - +:classes+ - additional classes for the actions
86
+ #
87
+ # @return [ActiveSupport::SafeBuffer] the HTML for a summary list row
88
+ # used in {govuk_summary_list}
89
+
90
+ def govuk_summary_list_row(summary_list_item, any_row_has_actions)
91
+ item_has_actions = summary_list_item.dig(:actions, :items).present?
92
+ summary_list_item_classes = "govuk-summary-list__row #{'govuk-summary-list__row--no-actions' if any_row_has_actions && !item_has_actions}".rstrip
93
+ summary_list_item_classes += " #{summary_list_item[:classes]}".rstrip
94
+
95
+ tag.div(class: summary_list_item_classes) do
96
+ concat(tag.dt(summary_list_item[:key][:text], class: govuk_summary_list_cell_classes(:key, summary_list_item)))
97
+ concat(tag.dd(summary_list_item[:value][:text], class: govuk_summary_list_cell_classes(:value, summary_list_item)))
98
+ concat(tag.dd(govuk_summary_list_actions(summary_list_item[:actions]), class: govuk_summary_list_cell_classes(:actions, summary_list_item))) if item_has_actions
99
+ end
100
+ end
101
+
102
+ # rubocop:enable Metrics/AbcSize
103
+
104
+ # Generates the HTML for a summary list actions used in {govuk_summary_list_row}
105
+ #
106
+ # @param summary_list_actions [Hash] the actions for the summary list
107
+ #
108
+ # @option summary_list_actions [Hash] :items the action items (see {govuk_summary_list_action_link})
109
+ # @option summary_list_actions [String] :classes additional CSS classes for the summary row HTML
110
+ #
111
+ # @return [ActiveSupport::SafeBuffer] the HTML for the summary list actions
112
+ # used in {govuk_summary_list_row}
113
+
114
+ def govuk_summary_list_actions(summary_list_actions)
115
+ if summary_list_actions[:items].length == 1
116
+ govuk_summary_list_action_link(summary_list_actions[:items].first)
117
+ else
118
+ tag.ul(class: 'govuk-summary-list__actions-list') do
119
+ summary_list_actions[:items].each do |summary_list_actions_item|
120
+ concat(tag.li(govuk_summary_list_action_link(summary_list_actions_item), class: 'govuk-summary-list__actions-list-item'))
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ # Generates the HTML for a summary list action link used in {govuk_summary_list_actions}
127
+ #
128
+ # @param summary_list_action_item [Hash] an individual action ite,
129
+ #
130
+ # @option summary_list_action_item [String] :text text for the link
131
+ # @option summary_list_action_item [String] :href href for the link
132
+ # @option summary_list_action_item [String] :classes additional CSS classes for the summary link HTML
133
+ # @option summary_list_action_item [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
134
+ #
135
+ # @return [ActiveSupport::SafeBuffer] the HTML for the summary list action link
136
+ # used in {govuk_summary_list_row}
137
+
138
+ def govuk_summary_list_action_link(summary_list_action_item)
139
+ initialise_attributes_and_set_classes(summary_list_action_item, 'govuk-link')
140
+
141
+ link_to(summary_list_action_item[:href], **summary_list_action_item[:attributes]) do
142
+ concat(summary_list_action_item[:text])
143
+ concat(tag.span(summary_list_action_item[:visually_hidden_text], class: 'govuk-visually-hidden')) if summary_list_action_item[:visually_hidden_text]
144
+ end
145
+ end
146
+
147
+ # rubocop:disable Metrics/AbcSize
148
+
149
+ # Creates the wrapper for the govuk summary card used in {govuk_summary_list}
150
+ #
151
+ # @param govuk_summary_card_options [Hash] options for the summary card
152
+ #
153
+ # @option govuk_summary_card_options [Hash] :title options for the title section of the card header
154
+ # @option govuk_summary_card_options [Hash] :actions options for the summary card actions section (see {govuk_summary_card_actions})
155
+ # @option govuk_summary_card_options [String] :classes additional CSS classes for the summary card HTML
156
+ # @option govuk_summary_card_options [Hash] :attributes ({}) any additional attributes that will be added as part of the HTML
157
+ #
158
+ # @option title [String] :text the title of the card
159
+ # @option title [String] :heading_level (2) heading level, from 1 to 6
160
+ # @option title [String] :classes additional classes to add to the title wrapper
161
+ #
162
+ # @yield HTML for the summary list (see {_govuk_summary_list})
163
+ #
164
+ # @return [ActiveSupport::SafeBuffer] the HTML for the summary card that
165
+ # wraps round {_govuk_summary_list} and
166
+ # used in {govuk_summary_list}
167
+
168
+ def govuk_summary_card(**govuk_summary_card_options, &block)
169
+ initialise_attributes_and_set_classes(govuk_summary_card_options, 'govuk-summary-card')
170
+
171
+ tag.div(**govuk_summary_card_options[:attributes]) do
172
+ concat(tag.div(class: 'govuk-summary-card__title-wrapper') do
173
+ if govuk_summary_card_options[:title]
174
+ govuk_summary_card_options[:title][:heading_level] ||= 2
175
+
176
+ concat(tag.send(:"h#{govuk_summary_card_options[:title][:heading_level]}", govuk_summary_card_options[:title][:text], class: "govuk-summary-card__title #{govuk_summary_card_options[:title][:classes]}".rstrip))
177
+ end
178
+ concat(govuk_summary_card_actions(govuk_summary_card_options[:actions])) if govuk_summary_card_options[:actions]
179
+ end)
180
+ concat(tag.div(class: 'govuk-summary-card__content', &block))
181
+ end
182
+ end
183
+
184
+ # rubocop:enable Metrics/AbcSize
185
+
186
+ # Generates the HTML for a summary card actions used in {govuk_summary_card}
187
+ #
188
+ # @param actions [Hash] options for the summary card actions
189
+ #
190
+ # @option actions [String] :classes additional CSS classes for the summary card actions HTML
191
+ # @option actions [Array] :items the action item objects which are passed to {govuk_summary_list_action_link}
192
+ #
193
+ # @return [ActiveSupport::SafeBuffer] the HTML for the summary card actions
194
+ # used in {govuk_summary_card}
195
+
196
+ def govuk_summary_card_actions(actions)
197
+ action_classes = "govuk-summary-card__actions #{actions[:classes]}".rstrip
198
+
199
+ if actions[:items].length == 1
200
+ tag.div(class: action_classes) do
201
+ govuk_summary_list_action_link(actions[:items][0])
202
+ end
203
+ else
204
+ tag.ul(class: action_classes) do
205
+ actions[:items].each { |action_item| concat(tag.li(govuk_summary_list_action_link(action_item), class: 'govuk-summary-card__action')) }
206
+ end
207
+ end
208
+ end
209
+
210
+ # Generates a string containing the classes for the cell used in {govuk_summary_list_row}
211
+ #
212
+ # @param type [String] the type of the row. One of:
213
+ # - +'key'+
214
+ # - +'value'+
215
+ # - +'actions'+
216
+ # @param summary_list_item [Hash] see {govuk_summary_list_row}
217
+ #
218
+ # @return [String] the classes for a summary list cell
219
+
220
+ def govuk_summary_list_cell_classes(type, summary_list_item)
221
+ "govuk-summary-list__#{type} #{summary_list_item[type][:classes]}".rstrip
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_view'
4
+
5
+ require_relative '../shared_methods'
6
+
7
+ module CCS
8
+ module FrontendHelpers
9
+ module GovUKFrontend
10
+ # = GOV.UK Table
11
+ #
12
+ # This helper is used for generating the table component from the
13
+ # {https://design-system.service.gov.uk/components/table GDS - Components - Table}
14
+
15
+ module Table
16
+ include SharedMethods
17
+ include ActionView::Context
18
+ include ActionView::Helpers::TagHelper
19
+ include ActionView::Helpers::TextHelper
20
+
21
+ # Generates the HTML for the GOV.UK Table component
22
+ #
23
+ # @param rows [Array] array of table rows and cells. See {govuk_table_row}
24
+ # @param head [NilClass,Array] array of table head cells. See {govuk_table_head}
25
+ # @param govuk_table_options [Hash] options that will be used in customising the HTML
26
+ #
27
+ # @option govuk_table_options [String] :classes additional CSS classes for the table HTML
28
+ # @option govuk_table_options [String] :first_cell_is_header if set to true, first cell in table row will be a TH instead of a TD
29
+ # @option govuk_table_options [Hash] :caption options for a table caption. See {govuk_table_caption}
30
+ # @option govuk_table_options [Hash] :attributes ({}) any additional attributes that will be added as part of the HTML
31
+ #
32
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Table
33
+ # which can then be rendered on the page
34
+
35
+ def govuk_table(rows, head = nil, **govuk_table_options)
36
+ initialise_attributes_and_set_classes(govuk_table_options, 'govuk-table')
37
+
38
+ tag.table(**govuk_table_options[:attributes]) do
39
+ concat(govuk_table_caption(govuk_table_options[:caption])) if govuk_table_options[:caption]
40
+ concat(govuk_table_head(head)) if head
41
+ concat(tag.tbody(class: 'govuk-table__body') do
42
+ rows.each { |row| concat(govuk_table_row(row, govuk_table_options[:first_cell_is_header])) }
43
+ end)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # Generates the HTML for the the table caption used in {govuk_table}
50
+ #
51
+ # @param caption [Hash] options that are used to define the caption
52
+ #
53
+ # @option caption [String] :text the caption text
54
+ # @option caption [String] :classes additional CSS classes for the table caption
55
+ #
56
+ # @return [ActiveSupport::SafeBuffer] the HTML for the table caption used in {govuk_table}
57
+
58
+ def govuk_table_caption(caption)
59
+ tag.caption(caption[:text], class: "govuk-table__caption #{caption[:classes]}".rstrip)
60
+ end
61
+
62
+ # Generates the HTML for the table head used in {govuk_table}
63
+ #
64
+ # @param head [Array] an array of table head cells
65
+ #
66
+ # @option head [String] :text the text of the cell
67
+ # @option head [String] :classes additional CSS classes for the cell
68
+ # @option head [String] :format specify format of a cell
69
+ # @option head [Hash] :attributes ({}) any additional attributes that will be added as part of the cell
70
+ #
71
+ # @return [ActiveSupport::SafeBuffer] the HTML for the table head used in {govuk_table}
72
+
73
+ def govuk_table_head(head)
74
+ tag.thead(class: 'govuk-table__head') do
75
+ tag.tr(class: 'govuk-table__row') do
76
+ head.each do |cell|
77
+ initialise_attributes_and_set_classes(cell, 'govuk-table__header')
78
+
79
+ cell[:attributes][:class] += " govuk-table__header--#{cell[:format]}" if cell[:format]
80
+ cell[:attributes][:scope] = 'col'
81
+
82
+ concat(tag.th(cell[:text], **cell[:attributes]))
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ # Generates the HTML for a table row used in {govuk_table}
89
+ #
90
+ # @param row [Array] an array of a rows cells
91
+ # @param first_cell_is_header [Boolean] if set to true, first cell in the row will be a TH instead of a TD
92
+ #
93
+ # @option row [String] :text the text of the cell
94
+ # @option row [String] :classes additional CSS classes for the cell
95
+ # @option row [String] :format specify format of a cell
96
+ # @option row [Hash] :attributes ({}) any additional attributes that will be added as part of the cell
97
+ #
98
+ # @return [ActiveSupport::SafeBuffer] the HTML for a table row used in {govuk_table}
99
+
100
+ def govuk_table_row(row, first_cell_is_header)
101
+ tag.tr(class: 'govuk-table__row') do
102
+ row.each.with_index do |cell, index|
103
+ tag_type = if first_cell_is_header && index.zero?
104
+ initialise_attributes_and_set_classes(cell, 'govuk-table__header')
105
+
106
+ cell[:attributes][:scope] = 'row'
107
+
108
+ :th
109
+ else
110
+ initialise_attributes_and_set_classes(cell, 'govuk-table__cell')
111
+
112
+ cell[:attributes][:class] += " govuk-table__cell--#{cell[:format]}" if cell[:format]
113
+
114
+ :td
115
+ end
116
+
117
+ concat(tag.send(tag_type, cell[:text], **cell[:attributes]))
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_view'
4
+
5
+ require_relative '../shared_methods'
6
+
7
+ module CCS
8
+ module FrontendHelpers
9
+ module GovUKFrontend
10
+ # = GOV.UK Tabs
11
+ #
12
+ # This helper is used for generating the tabs component from the
13
+ # {https://design-system.service.gov.uk/components/tabs GDS - Components - Tabs}
14
+
15
+ module Tabs
16
+ include SharedMethods
17
+ include ActionView::Context
18
+ include ActionView::Helpers::FormTagHelper
19
+ include ActionView::Helpers::TagHelper
20
+ include ActionView::Helpers::TextHelper
21
+ include ActionView::Helpers::UrlHelper
22
+
23
+ # Generates the HTML for the GOV.UK Tabs component
24
+ #
25
+ # @param items [Array] array of tab items. See {govuk_tabs_list_item}
26
+ # @param title [NilClass,String] title for the tabs table of contents
27
+ # @param govuk_tabs_options [Hash] options that will be used in customising the HTML
28
+ #
29
+ # @option govuk_tabs_options [String] :classes additional CSS classes for the tabs HTML
30
+ # @option govuk_tabs_options [String] :id_prefix prefix id for each tab item if no id is specified on each item
31
+ # @option govuk_tabs_options [Hash] :attributes ({}) any additional attributes that will be added as part of the HTML
32
+ #
33
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Tabs
34
+ # which can then be rendered on the page
35
+
36
+ def govuk_tabs(items, title = 'Contents', **govuk_tabs_options)
37
+ initialise_attributes_and_set_classes(govuk_tabs_options, 'govuk-tabs')
38
+ set_data_module(govuk_tabs_options, 'govuk-tabs')
39
+
40
+ id_prefix = govuk_tabs_options[:id_prefix] || sanitize_to_id(title.downcase)
41
+
42
+ tag.div(**govuk_tabs_options[:attributes]) do
43
+ concat(tag.h2(title, class: 'govuk-tabs__title'))
44
+ concat(tag.ul(class: 'govuk-tabs__lis') do
45
+ items.each.with_index(1) { |list_item, index| concat(govuk_tabs_list_item(list_item, index, id_prefix)) }
46
+ end)
47
+ items.each.with_index(1) { |panel_item, index| concat(govuk_tabs_panel_item(panel_item[:panel], index)) }
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # Generates the HTML for a tab list item used in {govuk_tabs}
54
+ #
55
+ # @param list_item [Hash] options used to form the tab
56
+ # @param index [Integer] the index of the tab
57
+ # @param id_prefix [String] prefix id for a tab item if no id is specified
58
+ #
59
+ # @option list_item [String] :label the text label of a tab item
60
+ # @option list_item [Hash] :panel content for panel. See {govuk_tabs_panel_item}
61
+ # @option list_item [Hash] :attributes ({}) any additional attributes that will be added as part of the tab link HTML
62
+ #
63
+ # @return [ActiveSupport::SafeBuffer] the HTML for a tab list item used in {govuk_tabs}
64
+
65
+ def govuk_tabs_list_item(list_item, index, id_prefix)
66
+ (list_item[:attributes] ||= {})[:class] = 'govuk-tabs__tab'
67
+ (list_item[:panel][:attributes] ||= {})[:id] ||= "#{id_prefix}-#{index}"
68
+
69
+ tag.li(class: "govuk-tabs__list-item #{'govuk-tabs__list-item--selected' if index == 1}".rstrip) do
70
+ link_to(list_item[:label], "##{list_item[:panel][:attributes][:id]}", **list_item[:attributes])
71
+ end
72
+ end
73
+
74
+ # Generates the HTML for a tab panel used in {govuk_tabs}
75
+ #
76
+ # @param panel_item [Hash] options used to form the tab panel
77
+ # @param index [Integer] the index of the tab
78
+ #
79
+ # @option panel_item [ActiveSupport::SafeBuffer] :content HTML to use within the each tab panel
80
+ # @option panel_item [String] :text if +:content+ is blank then this is the text within the panel
81
+ # @option panel_item [Hash] :attributes ({}) any additional attributes that will be added as part of the tab panel HTML
82
+ #
83
+ # @return [ActiveSupport::SafeBuffer] the HTML for a tab panel used in {govuk_tabs}
84
+
85
+ def govuk_tabs_panel_item(panel_item, index)
86
+ panel_item[:attributes][:class] = "govuk-tabs__panel #{'govuk-tabs__panel--hidden' if index > 1}".rstrip
87
+
88
+ tag.div(**panel_item[:attributes]) do
89
+ panel_item[:content] || tag.p(panel_item[:text], class: 'govuk-body')
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end