crown_marketplace_utils 0.1.0.beta.2 → 0.1.0.beta.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +44 -29
- data/README.md +35 -12
- data/crown_marketplace_utils.gemspec +9 -8
- data/lib/crown_marketplace_utils/gov_uk_helper/details.rb +1 -1
- data/lib/crown_marketplace_utils/gov_uk_helper/error_message.rb +1 -1
- data/lib/crown_marketplace_utils/gov_uk_helper/field/character_count.rb +193 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field/checkboxes.rb +209 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field/input.rb +160 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field/radios.rb +205 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field/select.rb +166 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field/textarea.rb +127 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/field.rb +263 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/fieldset.rb +75 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/form_group.rb +0 -3
- data/lib/crown_marketplace_utils/gov_uk_helper/header.rb +172 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/label.rb +97 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/notification_banner.rb +139 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/pagination.rb +214 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/step_by_step_navigation.rb +225 -0
- data/lib/crown_marketplace_utils/gov_uk_helper/tag.rb +39 -0
- data/lib/crown_marketplace_utils/gov_uk_helper.rb +28 -0
- data/lib/crown_marketplace_utils/version.rb +1 -1
- metadata +58 -30
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module CrownMarketplaceUtils
|
6
|
+
module GovUkHelper
|
7
|
+
# = GOV.UK Header
|
8
|
+
#
|
9
|
+
# This helper is used for generating the header component from the
|
10
|
+
# {https://design-system.service.gov.uk/components/header GDS - Components - Header}
|
11
|
+
|
12
|
+
module Header
|
13
|
+
include ActionView::Context
|
14
|
+
include ActionView::Helpers::FormTagHelper
|
15
|
+
include ActionView::Helpers::TagHelper
|
16
|
+
include ActionView::Helpers::TextHelper
|
17
|
+
include ActionView::Helpers::UrlHelper
|
18
|
+
|
19
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
20
|
+
|
21
|
+
# Generates the HTML for the GOV.UK Header component
|
22
|
+
#
|
23
|
+
# @param govuk_header_options [Hash] options that will be used in customising the HTML
|
24
|
+
#
|
25
|
+
# @option govuk_header_options [String] :classes additional CSS classes for the header HTML
|
26
|
+
# @option govuk_header_options [Hash] :container_options (see: {govuk_header_container})
|
27
|
+
# @option govuk_header_options [Hash] :service_options (see: {govuk_header_service_name})
|
28
|
+
# @option govuk_header_options [Hash] :navigation_options (see: {govuk_header_navigation})
|
29
|
+
# @option govuk_header_options [Hash] :attributes ({data: { module: 'govuk-header' }})
|
30
|
+
# any additional attributes that will added as part of the HTML
|
31
|
+
#
|
32
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Header
|
33
|
+
# which can then be rendered on the page
|
34
|
+
|
35
|
+
def govuk_header(**govuk_header_options)
|
36
|
+
govuk_header_classes = ['govuk-header']
|
37
|
+
govuk_header_classes << govuk_header_options[:classes]
|
38
|
+
govuk_header_options[:attributes] ||= {}
|
39
|
+
(govuk_header_options[:attributes][:data] ||= {}).merge!({ module: 'govuk-header' })
|
40
|
+
|
41
|
+
tag.header(class: govuk_header_classes, role: 'banner', **govuk_header_options[:attributes]) do
|
42
|
+
capture do
|
43
|
+
concat(govuk_header_container(govuk_header_options[:container_options] || {}))
|
44
|
+
if govuk_header_options[:service_options].present? || govuk_header_options[:navigation_options].present?
|
45
|
+
concat(tag.div(class: 'govuk-header__content') do
|
46
|
+
capture do
|
47
|
+
concat(govuk_header_service_name(service_options)) if govuk_header_options[:service_options].present?
|
48
|
+
concat(govuk_header_navigation(navigation_options)) if govuk_header_options[:navigation_options].present?
|
49
|
+
end
|
50
|
+
end)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Generates the header container with the logo for {govuk_header}
|
61
|
+
#
|
62
|
+
# @param container_options [Hash] options that will be used in customising the HTML
|
63
|
+
#
|
64
|
+
# @option container_options [String] :classes additional CSS classes for the container HTML
|
65
|
+
# @option container_options [String] :home_url the URL of the homepage. Defaults to +/+
|
66
|
+
# @option container_options [String] :product_name used when the product name follows on directly from ‘GOV.UK’
|
67
|
+
# @option container_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
|
68
|
+
#
|
69
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the header container which is used in {govuk_header}
|
70
|
+
|
71
|
+
def govuk_header_container(container_options)
|
72
|
+
govuk_header_classes = ['govuk-header__container']
|
73
|
+
govuk_header_classes << (container_options[:classes] || 'govuk-width-container')
|
74
|
+
|
75
|
+
tag.div(class: govuk_header_classes) do
|
76
|
+
tag.div(class: 'govuk-header__logo') do
|
77
|
+
link_to(container_options[:home_url] || '/', class: 'govuk-header__link govuk-header__link--homepage') do
|
78
|
+
capture do
|
79
|
+
concat(tag.span(class: 'govuk-header__logotype') do
|
80
|
+
capture do
|
81
|
+
concat(tag.svg(class: 'govuk-header__logotype-crown', xmlns: 'http://www.w3.org/2000/svg', height: '30', width: '36', aria: { hidden: 'true' }, focusable: 'false', viewBox: '0 0 132 97') do
|
82
|
+
tag.path(fill: 'currentColor', 'fill-rule': 'evenodd', d: 'M25 30.2c3.5 1.5 7.7-.2 9.1-3.7 1.5-3.6-.2-7.8-3.9-9.2-3.6-1.4-7.6.3-9.1 3.9-1.4 3.5.3 7.5 3.9 9zM9 39.5c3.6 1.5 7.8-.2 9.2-3.7 1.5-3.6-.2-7.8-3.9-9.1-3.6-1.5-7.6.2-9.1 3.8-1.4 3.5.3 7.5 3.8 9zM4.4 57.2c3.5 1.5 7.7-.2 9.1-3.8 1.5-3.6-.2-7.7-3.9-9.1-3.5-1.5-7.6.3-9.1 3.8-1.4 3.5.3 7.6 3.9 9.1zm38.3-21.4c3.5 1.5 7.7-.2 9.1-3.8 1.5-3.6-.2-7.7-3.9-9.1-3.6-1.5-7.6.3-9.1 3.8-1.3 3.6.4 7.7 3.9 9.1zm64.4-5.6c-3.6 1.5-7.8-.2-9.1-3.7-1.5-3.6.2-7.8 3.8-9.2 3.6-1.4 7.7.3 9.2 3.9 1.3 3.5-.4 7.5-3.9 9zm15.9 9.3c-3.6 1.5-7.7-.2-9.1-3.7-1.5-3.6.2-7.8 3.7-9.1 3.6-1.5 7.7.2 9.2 3.8 1.5 3.5-.3 7.5-3.8 9zm4.7 17.7c-3.6 1.5-7.8-.2-9.2-3.8-1.5-3.6.2-7.7 3.9-9.1 3.6-1.5 7.7.3 9.2 3.8 1.3 3.5-.4 7.6-3.9 9.1zM89.3 35.8c-3.6 1.5-7.8-.2-9.2-3.8-1.4-3.6.2-7.7 3.9-9.1 3.6-1.5 7.7.3 9.2 3.8 1.4 3.6-.3 7.7-3.9 9.1zM69.7 17.7l8.9 4.7V9.3l-8.9 2.8c-.2-.3-.5-.6-.9-.9L72.4 0H59.6l3.5 11.2c-.3.3-.6.5-.9.9l-8.8-2.8v13.1l8.8-4.7c.3.3.6.7.9.9l-5 15.4v.1c-.2.8-.4 1.6-.4 2.4 0 4.1 3.1 7.5 7 8.1h.2c.3 0 .7.1 1 .1.4 0 .7 0 1-.1h.2c4-.6 7.1-4.1 7.1-8.1 0-.8-.1-1.7-.4-2.4V34l-5.1-15.4c.4-.2.7-.6 1-.9zM66 92.8c16.9 0 32.8 1.1 47.1 3.2 4-16.9 8.9-26.7 14-33.5l-9.6-3.4c1 4.9 1.1 7.2 0 10.2-1.5-1.4-3-4.3-4.2-8.7L108.6 76c2.8-2 5-3.2 7.5-3.3-4.4 9.4-10 11.9-13.6 11.2-4.3-.8-6.3-4.6-5.6-7.9 1-4.7 5.7-5.9 8-.5 4.3-8.7-3-11.4-7.6-8.8 7.1-7.2 7.9-13.5 2.1-21.1-8 6.1-8.1 12.3-4.5 20.8-4.7-5.4-12.1-2.5-9.5 6.2 3.4-5.2 7.9-2 7.2 3.1-.6 4.3-6.4 7.8-13.5 7.2-10.3-.9-10.9-8-11.2-13.8 2.5-.5 7.1 1.8 11 7.3L80.2 60c-4.1 4.4-8 5.3-12.3 5.4 1.4-4.4 8-11.6 8-11.6H55.5s6.4 7.2 7.9 11.6c-4.2-.1-8-1-12.3-5.4l1.4 16.4c3.9-5.5 8.5-7.7 10.9-7.3-.3 5.8-.9 12.8-11.1 13.8-7.2.6-12.9-2.9-13.5-7.2-.7-5 3.8-8.3 7.1-3.1 2.7-8.7-4.6-11.6-9.4-6.2 3.7-8.5 3.6-14.7-4.6-20.8-5.8 7.6-5 13.9 2.2 21.1-4.7-2.6-11.9.1-7.7 8.8 2.3-5.5 7.1-4.2 8.1.5.7 3.3-1.3 7.1-5.7 7.9-3.5.7-9-1.8-13.5-11.2 2.5.1 4.7 1.3 7.5 3.3l-4.7-15.4c-1.2 4.4-2.7 7.2-4.3 8.7-1.1-3-.9-5.3 0-10.2l-9.5 3.4c5 6.9 9.9 16.7 14 33.5 14.8-2.1 30.8-3.2 47.7-3.2z')
|
83
|
+
end)
|
84
|
+
concat(tag.span('GOV.UK', class: 'govuk-header__logotype-text'))
|
85
|
+
end
|
86
|
+
end)
|
87
|
+
concat(tag.span(container_options[:product_name], class: 'govuk-header__product-name')) if container_options[:product_name]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# rubocop:enable Metrics/AbcSize
|
95
|
+
|
96
|
+
# Generates the service name for {govuk_header}
|
97
|
+
#
|
98
|
+
# @param service_options [Hash] options that will be used in customising the HTML
|
99
|
+
#
|
100
|
+
# @option service_options [String] :service_name the name of your service, included in the header
|
101
|
+
# @option service_options [String] :service_url URL for the service name anchor
|
102
|
+
#
|
103
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the service name which is used in {govuk_header}
|
104
|
+
|
105
|
+
def govuk_header_service_name(service_options)
|
106
|
+
if service_options[:service_url]
|
107
|
+
link_to(service_options[:service_name], service_options[:service_url], class: 'govuk-header__link govuk-header__service-name')
|
108
|
+
else
|
109
|
+
tag.span(service_options[:service_name], class: 'govuk-header__service-name')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Generates the navigation section for {govuk_header}
|
114
|
+
#
|
115
|
+
# @param navigation_options [Hash] options that will be used in customising the HTML
|
116
|
+
#
|
117
|
+
# @option navigation_options [String] :classes additional CSS classes for the navigation HTML
|
118
|
+
# @option navigation_options [String] :menu_button_text text of the button that opens the mobile navigation menu.
|
119
|
+
# By default, this is set to +'Menu'+.
|
120
|
+
# @option navigation_options [String] :menu_button_label text for the aria-label attribute of the button that opens the mobile navigation.
|
121
|
+
# Defaults to +'Show or hide menu'+.
|
122
|
+
# @option navigation_options [Array] :items the navigation items that will be rendered on the page (see {govuk_header_navigation_item})
|
123
|
+
#
|
124
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the navigation section which is used in {govuk_header}
|
125
|
+
|
126
|
+
def govuk_header_navigation(navigation_options)
|
127
|
+
menu_button_text = navigation_options[:menu_button_text] || 'Menu'
|
128
|
+
menu_button_label = navigation_options[:menu_button_label] || 'Show or hide menu'
|
129
|
+
|
130
|
+
govuk_header_navigation_classes = ['govuk-header__navigation']
|
131
|
+
govuk_header_navigation_classes << navigation_options[:classes]
|
132
|
+
|
133
|
+
tag.nav(class: govuk_header_navigation_classes, aria: { label: menu_button_text }) do
|
134
|
+
capture do
|
135
|
+
concat(button_tag(menu_button_text, class: 'govuk-header__menu-button govuk-js-header-toggle', type: 'button', hidden: true, aria: { controls: 'navigation', label: menu_button_label, }))
|
136
|
+
concat(tag.ul(id: 'navigation', class: 'govuk-header__navigation-list') do
|
137
|
+
capture do
|
138
|
+
navigation_options[:items].each do |navigation_item|
|
139
|
+
concat(govuk_header_navigation_item(navigation_item))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Generates a navigation item for {govuk_header_navigation}
|
148
|
+
#
|
149
|
+
# @param navigation_item [Hash] options that will be used in customising the HTML
|
150
|
+
#
|
151
|
+
# @option navigation_item [Boolean] :active flag to mark the navigation item as active or not
|
152
|
+
# @option navigation_item [String] :text text for the navigation item
|
153
|
+
# @option navigation_item [String] :href URL of the navigation item anchor
|
154
|
+
# @option navigation_item [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
|
155
|
+
#
|
156
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for a navigation item which is used in {govuk_header_navigation}
|
157
|
+
|
158
|
+
def govuk_header_navigation_item(navigation_item)
|
159
|
+
govuk_header_navigation_item_classes = ['govuk-header__navigation-item']
|
160
|
+
govuk_header_navigation_item_classes << 'govuk-header__navigation-item--active' if navigation_item[:active]
|
161
|
+
|
162
|
+
tag.li(class: govuk_header_navigation_item_classes) do
|
163
|
+
if navigation_item[:href]
|
164
|
+
link_to(navigation_item[:text], navigation_item[:href], class: 'govuk-header__link', **(navigation_item[:attributes] || {}))
|
165
|
+
else
|
166
|
+
concat(navigation_item[:text])
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module CrownMarketplaceUtils
|
6
|
+
module GovUkHelper
|
7
|
+
# = GOV.UK label
|
8
|
+
#
|
9
|
+
# This helper is used for generating the label component from the Government Design Systems
|
10
|
+
|
11
|
+
module Label
|
12
|
+
include ActionView::Context
|
13
|
+
include ActionView::Helpers::TagHelper
|
14
|
+
include ActionView::Helpers::TextHelper
|
15
|
+
include ActionView::Helpers::FormTagHelper
|
16
|
+
|
17
|
+
# Generates the HTML for the GOV.UK label component
|
18
|
+
#
|
19
|
+
# @param attribute [String, Symbol] the attribute of the input that requires a label
|
20
|
+
# @param label_text [String] the label text, it is ignored if a block is given
|
21
|
+
# @param govuk_label_options [Hash] options that will be used in customising the HTML
|
22
|
+
#
|
23
|
+
# @option govuk_label_options [String] :classes additional CSS classes for the label HTML
|
24
|
+
# @option govuk_label_options [Boolean] :is_page_heading (false) if the legend is also the heading it will rendered in a h1
|
25
|
+
# @option govuk_label_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
|
26
|
+
#
|
27
|
+
# @yield HTML that will be contained within the 'govuk-label' label
|
28
|
+
#
|
29
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Label
|
30
|
+
# which can then be rendered on the page
|
31
|
+
|
32
|
+
def govuk_label(attribute, label_text = nil, **govuk_label_options)
|
33
|
+
_govuk_label(**govuk_label_options) do |govuk_label_classes, govuk_label_attributes|
|
34
|
+
label_tag(attribute, class: govuk_label_classes, **govuk_label_attributes) do
|
35
|
+
if block_given?
|
36
|
+
yield
|
37
|
+
else
|
38
|
+
concat(label_text)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Generates the HTML for the GOV.UK label component using an ActionView::Helpers::FormBuilder
|
45
|
+
#
|
46
|
+
# @param form [ActionView::Helpers::FormBuilder] :form the form builder used to create the label
|
47
|
+
# @param attribute [String, Symbol] the attribute of the input that requires a label
|
48
|
+
# @param label_text [String] the label text, it is ignored if a block is given
|
49
|
+
# @param govuk_label_options [Hash] options that will be used in customising the HTML
|
50
|
+
#
|
51
|
+
# @option (see govuk_label)
|
52
|
+
#
|
53
|
+
# @yield (see govuk_label)
|
54
|
+
#
|
55
|
+
# @return (see govuk_label)
|
56
|
+
|
57
|
+
def govuk_label_with_form(form, attribute, label_text = nil, **govuk_label_options, &block)
|
58
|
+
_govuk_label(**govuk_label_options) do |govuk_label_classes, govuk_label_attributes|
|
59
|
+
if block_given?
|
60
|
+
form.label(attribute, class: govuk_label_classes, **govuk_label_attributes, &block)
|
61
|
+
else
|
62
|
+
form.label(attribute, label_text, class: govuk_label_classes, **govuk_label_attributes)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Wrapper method used by {#govuk_label} and {#govuk_label_with_form} to generate the Label HTML
|
70
|
+
#
|
71
|
+
# @param govuk_label_options [Hash] options that will be used in customising the HTML
|
72
|
+
#
|
73
|
+
# @option (see govuk_label)
|
74
|
+
#
|
75
|
+
# @yield the label HTML generated by {#govuk_label} or {#govuk_label_with_form}
|
76
|
+
#
|
77
|
+
# @yieldparam govuk_label_classes [Array] the classes for the label HTML
|
78
|
+
# @yieldparam govuk_label_attributes [Hash] additional attributes that will added as part of the HTML
|
79
|
+
#
|
80
|
+
# @return (see govuk_label)
|
81
|
+
|
82
|
+
def _govuk_label(**govuk_label_options)
|
83
|
+
govuk_label_classes = ['govuk-label']
|
84
|
+
govuk_label_classes << govuk_label_options[:classes]
|
85
|
+
govuk_label_options[:attributes] ||= {}
|
86
|
+
|
87
|
+
label_html = yield(govuk_label_classes, govuk_label_options[:attributes])
|
88
|
+
|
89
|
+
if govuk_label_options[:is_page_heading]
|
90
|
+
tag.h1(label_html, class: 'govuk-label-wrapper')
|
91
|
+
else
|
92
|
+
label_html
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module CrownMarketplaceUtils
|
6
|
+
module GovUkHelper
|
7
|
+
# = GOV.UK Notification Banner
|
8
|
+
#
|
9
|
+
# This helper is used for generating the notification banner component from the
|
10
|
+
# {https://design-system.service.gov.uk/components/notification-banner GDS - Components - Notification banner}
|
11
|
+
|
12
|
+
module NotificationBanner
|
13
|
+
include ActionView::Context
|
14
|
+
include ActionView::Helpers::TagHelper
|
15
|
+
include ActionView::Helpers::TextHelper
|
16
|
+
|
17
|
+
# Generates the HTML for the GOV.UK Notification banner component
|
18
|
+
#
|
19
|
+
# @param text [String] the text that will be used for the heading in the content section of the banner.
|
20
|
+
# It is ignored if a block is given
|
21
|
+
# @param success_banner [Boolean] will use the success banner options if this is set to true
|
22
|
+
# @param govuk_notification_banner_options [Hash] options that will be used in customising the HTML
|
23
|
+
#
|
24
|
+
# @option govuk_notification_banner_options [String] :classes additional CSS classes for the notification banner HTML
|
25
|
+
# @option govuk_notification_banner_options [String] :title_text ('Important') the title text shown at the top of the banner
|
26
|
+
# @option govuk_notification_banner_options [String] :title_id ('govuk-notification-banner-title') the ID for the title text
|
27
|
+
# @option govuk_notification_banner_options [String] :role ('region') the role for the banner
|
28
|
+
# @option govuk_notification_banner_options [String] :heading_level (2) the heading level for the title text
|
29
|
+
# @option govuk_notification_banner_options [Hash] :attributes ({data: { module: 'govuk-notification-banner' }, aria: { labelledby: 'govuk-notification-banner-title' }})
|
30
|
+
# any additional attributes that will added as part of the HTML
|
31
|
+
#
|
32
|
+
# @yield HTML that will be contained within the 'govuk-notification-banner__content' div
|
33
|
+
#
|
34
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Notification banner
|
35
|
+
# which can then be rendered on the page
|
36
|
+
|
37
|
+
def govuk_notification_banner(text = nil, success_banner = false, **govuk_notification_banner_options)
|
38
|
+
banner_options = fetch_banner_options(success_banner, govuk_notification_banner_options)
|
39
|
+
govuk_notification_banner_classes = fetch_banner_classes(banner_options, govuk_notification_banner_options)
|
40
|
+
govuk_notification_banner_attributes = fetch_banner_attributes(banner_options, govuk_notification_banner_options)
|
41
|
+
|
42
|
+
tag.div(class: govuk_notification_banner_classes, role: banner_options[:role], **govuk_notification_banner_attributes) do
|
43
|
+
capture do
|
44
|
+
concat(tag.div(class: 'govuk-notification-banner__header') do
|
45
|
+
tag.send(:"h#{govuk_notification_banner_options[:heading_level] || 2}", banner_options[:title_text], class: 'govuk-notification-banner__title', id: banner_options[:title_id])
|
46
|
+
end)
|
47
|
+
concat(tag.div(class: 'govuk-notification-banner__content') do
|
48
|
+
if block_given?
|
49
|
+
yield
|
50
|
+
else
|
51
|
+
tag.p(text, class: 'govuk-notification-banner__heading')
|
52
|
+
end
|
53
|
+
end)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Determines the banner options to be used for {#govuk_notification_banner}
|
61
|
+
#
|
62
|
+
# @param success_banner [Boolean] will use the success banner options if this is set to true
|
63
|
+
# @param govuk_notification_banner_options [Hash] options that will be used in customising the HTML
|
64
|
+
#
|
65
|
+
# @option govuk_notification_banner_options [String] :title_text ('Important') the title text shown at the top of the banner
|
66
|
+
# @option govuk_notification_banner_options [String] :title_id ('govuk-notification-banner-title') the ID for the title text
|
67
|
+
# @option govuk_notification_banner_options [String] :role ('region') the role for the banner
|
68
|
+
#
|
69
|
+
# @return [Hash] contains the following options used in {#govuk_notification_banner}:
|
70
|
+
# - +classes+
|
71
|
+
# - +title_text+
|
72
|
+
# - +title_id+
|
73
|
+
# - +role+
|
74
|
+
|
75
|
+
def fetch_banner_options(success_banner, govuk_notification_banner_options)
|
76
|
+
banner_options = DEFAULT_OPTIONS.dup
|
77
|
+
|
78
|
+
banner_options.merge!(SUCCESS_BANNER_OPTIONS) if success_banner
|
79
|
+
|
80
|
+
govuk_notification_banner_options.each do |key, value|
|
81
|
+
banner_options[key] = value if banner_options.key?(key)
|
82
|
+
end
|
83
|
+
|
84
|
+
banner_options
|
85
|
+
end
|
86
|
+
|
87
|
+
# Determines the banner classes to be used for {#govuk_notification_banner}
|
88
|
+
#
|
89
|
+
# @param banner_options [Hash] this is the return value from {#fetch_banner_options}
|
90
|
+
# @param govuk_notification_banner_options [Hash] options that will be used in customising the HTML
|
91
|
+
#
|
92
|
+
# @option govuk_notification_banner_options [String] :classes additional CSS classes for the notification banner HTML
|
93
|
+
#
|
94
|
+
# @return [Array<String>] an array of classes to be used in {#govuk_notification_banner}
|
95
|
+
|
96
|
+
def fetch_banner_classes(banner_options, govuk_notification_banner_options)
|
97
|
+
govuk_notification_banner_classes = ['govuk-notification-banner']
|
98
|
+
govuk_notification_banner_classes << govuk_notification_banner_options[:classes]
|
99
|
+
govuk_notification_banner_classes << banner_options[:classes]
|
100
|
+
|
101
|
+
govuk_notification_banner_classes
|
102
|
+
end
|
103
|
+
|
104
|
+
# Default HTML attributes for {#govuk_notification_banner}
|
105
|
+
#
|
106
|
+
# @param banner_options [Hash] this is the return value from {#fetch_banner_options}
|
107
|
+
# @param govuk_notification_banner_options [Hash] options that will be used in customising the HTML
|
108
|
+
#
|
109
|
+
# @option govuk_notification_banner_options [Hash] :attributes ({data: { module: 'govuk-notification-banner' }, aria: { labelledby: 'govuk-notification-banner-title' }})
|
110
|
+
# any additional attributes that will added as part of the HTML
|
111
|
+
#
|
112
|
+
# @return [Hash] contains the default attributes for {#govuk_notification_banner} and any additional attributes that were passed
|
113
|
+
|
114
|
+
def fetch_banner_attributes(banner_options, govuk_notification_banner_options)
|
115
|
+
govuk_notification_banner_attributes = govuk_notification_banner_options[:attributes] || {}
|
116
|
+
(govuk_notification_banner_attributes[:data] ||= {}).merge!({ module: 'govuk-notification-banner' })
|
117
|
+
(govuk_notification_banner_attributes[:aria] ||= {}).merge!({ labelledby: banner_options[:title_id] })
|
118
|
+
|
119
|
+
govuk_notification_banner_attributes
|
120
|
+
end
|
121
|
+
|
122
|
+
# Default options used in normal versions of {#govuk_notification_banner}
|
123
|
+
|
124
|
+
DEFAULT_OPTIONS = {
|
125
|
+
title_text: 'Important',
|
126
|
+
title_id: 'govuk-notification-banner-title',
|
127
|
+
role: 'region'
|
128
|
+
}.freeze
|
129
|
+
|
130
|
+
# Options specific for the success version of {#govuk_notification_banner}
|
131
|
+
|
132
|
+
SUCCESS_BANNER_OPTIONS = {
|
133
|
+
classes: 'govuk-notification-banner--success',
|
134
|
+
title_text: 'Success',
|
135
|
+
role: 'alert'
|
136
|
+
}.freeze
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
module CrownMarketplaceUtils
|
6
|
+
module GovUkHelper
|
7
|
+
# = GOV.UK Pagination
|
8
|
+
#
|
9
|
+
# This helper is used for generating the pagination component from the
|
10
|
+
# {https://design-system.service.gov.uk/components/pagination GDS - Components - Pagination}
|
11
|
+
|
12
|
+
module Pagination
|
13
|
+
include ActionView::Context
|
14
|
+
include ActionView::Helpers::TagHelper
|
15
|
+
include ActionView::Helpers::TextHelper
|
16
|
+
include ActionView::Helpers::UrlHelper
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
19
|
+
|
20
|
+
# Generates the HTML for the GOV.UK Pagination component
|
21
|
+
#
|
22
|
+
# @param govuk_pagination_options [Hash] options that will be used in customising the HTML
|
23
|
+
#
|
24
|
+
# @option govuk_pagination_options [String] :classes additional CSS classes for the pagination HTML
|
25
|
+
# @option govuk_pagination_options [Array] :items an array of items for the pagination (see: {govuk_pagination_items})
|
26
|
+
# @option govuk_pagination_options [Hash] :previous the previous link (see: {govuk_pagination_previous})
|
27
|
+
# @option govuk_pagination_options [Hash] :next the next link (see: {govuk_pagination_next})
|
28
|
+
# @option govuk_pagination_options [Hash] :attributes ({role: 'navigation', aria: { label: 'results' }})
|
29
|
+
# any additional attributes that will added as part of the HTML
|
30
|
+
#
|
31
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Pagination
|
32
|
+
# which can then be rendered on the page
|
33
|
+
|
34
|
+
def govuk_pagination(**govuk_pagination_options)
|
35
|
+
govuk_pagination_classes = ['govuk-pagination']
|
36
|
+
govuk_pagination_classes << govuk_pagination_options[:classes]
|
37
|
+
|
38
|
+
block_is_level = govuk_pagination_options[:items].blank? && (govuk_pagination_options[:next].present? || govuk_pagination_options[:previous].present?)
|
39
|
+
|
40
|
+
govuk_pagination_classes << 'govuk-pagination--block' if block_is_level
|
41
|
+
|
42
|
+
(govuk_pagination_options[:attributes] ||= {}).merge({ role: 'navigation' })
|
43
|
+
(govuk_pagination_options[:attributes][:aria] ||= {})[:label] ||= 'results'
|
44
|
+
|
45
|
+
tag.nav(class: govuk_pagination_classes, **govuk_pagination_options[:attributes]) do
|
46
|
+
capture do
|
47
|
+
concat(govuk_pagination_previous(block_is_level, **govuk_pagination_options[:previous])) if govuk_pagination_options[:previous]
|
48
|
+
concat(govuk_pagination_items(govuk_pagination_options[:items])) if govuk_pagination_options[:items]
|
49
|
+
concat(govuk_pagination_next(block_is_level, **govuk_pagination_options[:next])) if govuk_pagination_options[:next]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Generates the previous link for {govuk_pagination}
|
59
|
+
#
|
60
|
+
# @param block_is_level [Boolean] when there are no items, this will be true and will add extra classe
|
61
|
+
# to the link to make the next and previous pagination links level
|
62
|
+
# @param govuk_pagination_previous_options [Hash] options that will be used in customising the HTML
|
63
|
+
#
|
64
|
+
# @option govuk_pagination_previous_options [String] :href the URL for the link
|
65
|
+
# @option govuk_pagination_previous_options [String] :text ('Previous') the text for the link
|
66
|
+
# @option govuk_pagination_previous_options [String] :lable_text additional text for the link when the pagination block is level
|
67
|
+
# @option govuk_pagination_previous_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
|
68
|
+
#
|
69
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the previous link which is used in {govuk_pagination}
|
70
|
+
|
71
|
+
def govuk_pagination_previous(block_is_level, **govuk_pagination_previous_options)
|
72
|
+
govuk_pagination_previous_classes = ['govuk-pagination__link-title']
|
73
|
+
govuk_pagination_previous_classes << 'govuk-pagination__link-title--decorated' if block_is_level && !govuk_pagination_previous_options[:lable_text]
|
74
|
+
|
75
|
+
tag.div(class: 'govuk-pagination__prev') do
|
76
|
+
link_to(govuk_pagination_previous_options[:href], class: 'govuk-link govuk-pagination__link', rel: 'prev', **(govuk_pagination_previous_options[:attributes] || {})) do
|
77
|
+
capture do
|
78
|
+
concat(govuk_pagination_icon(:prev))
|
79
|
+
concat(tag.span(govuk_pagination_previous_options[:text] || 'Previous', class: govuk_pagination_previous_classes))
|
80
|
+
concat(govuk_pagination_icon_label_text(block_is_level, govuk_pagination_previous_options[:lable_text]))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Generates the next link for {govuk_pagination}
|
87
|
+
#
|
88
|
+
# @param block_is_level [Boolean] when there are no items, this will be true and will add extra classe
|
89
|
+
# to the link to make the next and previous pagination links level
|
90
|
+
# @param govuk_pagination_next_options [Hash] options that will be used in customising the HTML
|
91
|
+
#
|
92
|
+
# @option govuk_pagination_next_options [String] :href the URL for the link
|
93
|
+
# @option govuk_pagination_next_options [String] :text ('Next') the text for the link
|
94
|
+
# @option govuk_pagination_next_options [String] :lable_text additional text for the link when the pagination block is level
|
95
|
+
# @option govuk_pagination_next_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
|
96
|
+
#
|
97
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the next link which is used in {govuk_pagination}
|
98
|
+
|
99
|
+
def govuk_pagination_next(block_is_level, **govuk_pagination_next_options)
|
100
|
+
govuk_pagination_next_classes = ['govuk-pagination__link-title']
|
101
|
+
govuk_pagination_next_classes << 'govuk-pagination__link-title--decorated' if block_is_level && !govuk_pagination_next_options[:lable_text]
|
102
|
+
|
103
|
+
tag.div(class: 'govuk-pagination__next') do
|
104
|
+
link_to(govuk_pagination_next_options[:href], class: 'govuk-link govuk-pagination__link', rel: 'next', **(govuk_pagination_next_options[:attributes] || {})) do
|
105
|
+
capture do
|
106
|
+
concat(govuk_pagination_icon(:next)) if block_is_level
|
107
|
+
concat(tag.span(govuk_pagination_next_options[:text] || 'Next', class: govuk_pagination_next_classes))
|
108
|
+
concat(govuk_pagination_icon_label_text(block_is_level, govuk_pagination_next_options[:lable_text]))
|
109
|
+
concat(govuk_pagination_icon(:next)) unless block_is_level
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Generates the item links for {govuk_pagination}
|
116
|
+
#
|
117
|
+
# @param govuk_pagination_items [Array(Hash)] an array of item hashes for the pagination.
|
118
|
+
# There are two types of item:
|
119
|
+
# - {govuk_pagination_item_ellipsis ellipsis item}
|
120
|
+
# - {govuk_pagination_item_number number item}
|
121
|
+
#
|
122
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for the lits of items which is used in {govuk_pagination}
|
123
|
+
|
124
|
+
def govuk_pagination_items(govuk_pagination_items)
|
125
|
+
tag.ul(class: 'govuk-pagination__list') do
|
126
|
+
capture do
|
127
|
+
govuk_pagination_items.each do |govuk_pagination_item|
|
128
|
+
case govuk_pagination_item[:type]
|
129
|
+
when :ellipsis
|
130
|
+
concat(govuk_pagination_item_ellipsis)
|
131
|
+
when :number
|
132
|
+
concat(govuk_pagination_item_number(govuk_pagination_item))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Generates the icon for:
|
140
|
+
# - {govuk_pagination_previous}
|
141
|
+
# - {govuk_pagination_next}
|
142
|
+
#
|
143
|
+
# @param type [Symbol] the type of the pagination icon (+:prev+ or +:next+)
|
144
|
+
#
|
145
|
+
# @return [ActiveSupport::SafeBuffer]
|
146
|
+
|
147
|
+
def govuk_pagination_icon(type)
|
148
|
+
tag.svg(class: "govuk-pagination__icon govuk-pagination__icon--#{type}", xmlns: 'http://www.w3.org/2000/svg', height: '13', width: '15', aria: { hidden: 'true' }, focusable: 'false', viewBox: '0 0 15 13') do
|
149
|
+
tag.path(d: PAGINATION_ICON_PATHS[type])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Generates the label text for:
|
154
|
+
# - {govuk_pagination_previous}
|
155
|
+
# - {govuk_pagination_next}
|
156
|
+
#
|
157
|
+
# @param block_is_level [Boolean] when there are no items, this will be true
|
158
|
+
# @param label_text [String] the additional text for the link
|
159
|
+
#
|
160
|
+
# @return [ActiveSupport::SafeBuffer]
|
161
|
+
|
162
|
+
def govuk_pagination_icon_label_text(block_is_level, label_text)
|
163
|
+
return unless block_is_level && label_text
|
164
|
+
|
165
|
+
capture do
|
166
|
+
concat(tag.span(':', class: 'govuk-visually-hidden'))
|
167
|
+
concat(tag.span(label_text, class: 'govuk-pagination__link-label'))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Generates the ellipsis HTML for {govuk_pagination_items}
|
172
|
+
#
|
173
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for an ellipsis item which is used in {govuk_pagination_items}
|
174
|
+
|
175
|
+
def govuk_pagination_item_ellipsis
|
176
|
+
tag.li('⋯', class: 'govuk-pagination__item govuk-pagination__item--ellipses')
|
177
|
+
end
|
178
|
+
|
179
|
+
# Generates the number item HTML for {govuk_pagination_items}
|
180
|
+
#
|
181
|
+
# @param govuk_pagination_item [Hash] options that will be used in customising the HTML
|
182
|
+
#
|
183
|
+
# @option govuk_pagination_item [String] :href the URL for the link
|
184
|
+
# @option govuk_pagination_item [String] :number the number for the link
|
185
|
+
# @option govuk_pagination_item [String] :current is this item the current page
|
186
|
+
# @option govuk_pagination_item [Hash] :attributes ({aria: { label: 'Page <NUMBER>' } })
|
187
|
+
# any additional attributes that will added as part of the HTML
|
188
|
+
#
|
189
|
+
# @return [ActiveSupport::SafeBuffer] the HTML for an number item which is used in {govuk_pagination_items}
|
190
|
+
|
191
|
+
def govuk_pagination_item_number(govuk_pagination_item)
|
192
|
+
govuk_pagination_item_classes = ['govuk-pagination__item']
|
193
|
+
(govuk_pagination_item[:attributes] ||= {})[:aria] ||= {}
|
194
|
+
govuk_pagination_item[:attributes][:aria][:label] ||= "Page #{govuk_pagination_item[:number]}"
|
195
|
+
|
196
|
+
if govuk_pagination_item[:current]
|
197
|
+
govuk_pagination_item_classes << 'govuk-pagination__item--current'
|
198
|
+
govuk_pagination_item[:attributes][:aria][:current] = 'page'
|
199
|
+
end
|
200
|
+
|
201
|
+
tag.li(class: govuk_pagination_item_classes) do
|
202
|
+
link_to(govuk_pagination_item[:href], govuk_pagination_item[:number], class: 'govuk-link govuk-pagination__link', **govuk_pagination_item[:attributes])
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# The paths for the pagination next and previous icons
|
207
|
+
|
208
|
+
PAGINATION_ICON_PATHS = {
|
209
|
+
prev: 'm6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z',
|
210
|
+
next: 'm8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z'
|
211
|
+
}.freeze
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|