govuk_publishing_components 50.0.1 → 51.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +1 -1
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-search-tracker.js +19 -10
  4. data/app/assets/javascripts/govuk_publishing_components/components/add-another.js +7 -5
  5. data/app/assets/javascripts/govuk_publishing_components/components/cookie-banner.js +0 -3
  6. data/app/assets/javascripts/govuk_publishing_components/components/global-banner.js +62 -0
  7. data/app/assets/javascripts/govuk_publishing_components/lib/cookie-functions.js +1 -1
  8. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +30 -30
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_global-banner.scss +38 -0
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +2 -9
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_title.scss +6 -0
  12. data/app/views/govuk_publishing_components/audit/show.html.erb +7 -1
  13. data/app/views/govuk_publishing_components/component_guide/example.html.erb +8 -1
  14. data/app/views/govuk_publishing_components/component_guide/index.html.erb +7 -1
  15. data/app/views/govuk_publishing_components/component_guide/show.html.erb +8 -1
  16. data/app/views/govuk_publishing_components/components/_add_another.html.erb +20 -12
  17. data/app/views/govuk_publishing_components/components/_global_banner.html.erb +43 -0
  18. data/app/views/govuk_publishing_components/components/_inverse_header.html.erb +7 -1
  19. data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +6 -6
  20. data/app/views/govuk_publishing_components/components/_title.html.erb +0 -3
  21. data/app/views/govuk_publishing_components/components/docs/add_another.yml +12 -0
  22. data/app/views/govuk_publishing_components/components/docs/button.yml +9 -0
  23. data/app/views/govuk_publishing_components/components/docs/global_banner.yml +30 -0
  24. data/app/views/govuk_publishing_components/components/docs/inverse_header.yml +25 -1
  25. data/app/views/govuk_publishing_components/components/docs/layout_for_public.yml +2 -2
  26. data/app/views/govuk_publishing_components/components/docs/title.yml +0 -10
  27. data/lib/govuk_publishing_components/presenters/button_helper.rb +4 -1
  28. data/lib/govuk_publishing_components/presenters/shared_helper.rb +1 -6
  29. data/lib/govuk_publishing_components/version.rb +1 -1
  30. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e10e292cd3c42e84ad11ee8c1b6422d045d943fda0bae4cedad8b0969599af25
4
- data.tar.gz: 1ee25803f2c0d5c0d2c4ee8226cdbf0c6ece0c9704a2fd8c936f6bc7ce29c334
3
+ metadata.gz: cc93d3d2e0d58cb2889e655c2329ab804743dc817263461f04c1c67992a45b65
4
+ data.tar.gz: 3f0105fd23e588fbf9596cc8af2730f9f3b3eec848b2fa2c15c945d8a259702e
5
5
  SHA512:
6
- metadata.gz: a0e38c5c1395e359d5c3382da267ca85a888b05718b7e0e0d02e396857394967001dd5618147d27afb85db8beb24d4457e6f3f84e1b0e695350cd119269dd9c3
7
- data.tar.gz: 66130ce6c2961f001b4642ce37ab3ce079a7aa9ad18a64fe4dc359a591f57ed7828c115e7e4b0b0cf28ec664da5f30644d7148dc1d4d9fce09424186ee13e290
6
+ metadata.gz: c40f84acabd6a47fe2b46c29e1d759821eec65e16884dccf0feb0d88b868c2cfa11565d1fcdafa1e2f0cea536daf623fbe8233204762285c689fdcb6982f75b7
7
+ data.tar.gz: 806abfe7bf6f5b5ef250bde33701af3aaf80b6003588bcf21a1beb337a02370c900140f75f3e3670100a929c538c239160b8def9ca1a31c7e0acd3a8c31d3c9e
@@ -61,7 +61,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
61
61
  devolved_nations_banner: this.getElementAttribute('data-ga4-devolved-nations-banner') || undefined,
62
62
  cookie_banner: this.getBannerPresence('[data-ga4-cookie-banner]'),
63
63
  intervention: this.getBannerPresence('[data-ga4-intervention-banner]'),
64
- global_bar: this.getBannerPresence('[data-ga4-global-bar]'),
64
+ global_bar: this.getBannerPresence('[data-ga4-global-banner]'),
65
65
  query_string: this.getQueryString(),
66
66
  search_term: this.getSearchTerm(),
67
67
  tool_name: this.getToolName(),
@@ -14,6 +14,9 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
14
14
  this.section = this.$module.dataset.ga4SearchSection
15
15
  this.indexSection = this.$module.dataset.ga4SearchIndexSection
16
16
  this.indexSectionCount = this.$module.dataset.ga4SearchIndexSectionCount
17
+
18
+ // At the beginning, the user has not yet interacted with any form fields
19
+ this.triggeredAction = 'unchanged'
17
20
  }
18
21
 
19
22
  init () {
@@ -22,7 +25,11 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
22
25
  return
23
26
  }
24
27
 
25
- this.initialKeywords = this.$searchInput.value
28
+ // These event handlers do not send any tracking data, they only set internal state. They are
29
+ // added here so if the user hasn't given consent yet but does so later, we do not end up with
30
+ // inconsistent module state.
31
+ this.$module.addEventListener('change', event => this.setTriggeredAction(event))
32
+ this.$module.addEventListener('input', event => this.setTriggeredAction(event))
26
33
 
27
34
  if (window.GOVUK.getConsentCookie() && window.GOVUK.getConsentCookie().usage) {
28
35
  this.startModule()
@@ -35,16 +42,24 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
35
42
  this.$module.addEventListener('submit', event => this.trackSearch(event))
36
43
  }
37
44
 
45
+ setTriggeredAction (event) {
46
+ if (event.target.type === 'search') {
47
+ this.triggeredAction = 'search'
48
+ } else if (this.triggeredAction !== 'search') {
49
+ // The 'search' action always takes precedence over the 'filter' action, so only set the
50
+ // action to 'filter' if it is not already 'search'.
51
+ this.triggeredAction = 'filter'
52
+ }
53
+ }
54
+
38
55
  trackSearch () {
39
56
  // The original search input may have been removed from the DOM by the autocomplete component
40
57
  // if it is used, so make sure we are tracking the correct input
41
58
  this.$searchInput = this.$module.querySelector('input[type="search"]')
42
59
 
43
- if (this.skipTracking()) return
44
-
45
60
  const data = {
46
61
  event_name: 'search',
47
- action: 'search',
62
+ action: this.triggeredAction,
48
63
 
49
64
  type: this.type,
50
65
  section: this.section,
@@ -80,12 +95,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
80
95
  window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
81
96
  }
82
97
 
83
- skipTracking () {
84
- // Skip tracking for those events that we do not want to track: where the search term is
85
- // present, but has not changed from its initial value
86
- return this.searchTerm() !== '' && this.searchTerm() === this.initialKeywords
87
- }
88
-
89
98
  searchTerm () {
90
99
  const { standardiseSearchTerm } = window.GOVUK.analyticsGa4.core.trackFunctions
91
100
 
@@ -49,7 +49,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
49
49
 
50
50
  AddAnother.prototype.createRemoveButtons = function () {
51
51
  var fieldsets =
52
- document.querySelectorAll('.js-add-another__fieldset')
52
+ this.module.querySelectorAll('.js-add-another__fieldset')
53
53
  fieldsets.forEach(function (fieldset) {
54
54
  this.createRemoveButton(fieldset, this.removeExistingFieldset.bind(this))
55
55
  fieldset.querySelector('.js-add-another__destroy-checkbox').hidden = true
@@ -67,10 +67,12 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
67
67
  legend.textContent = this.module.dataset.fieldsetLegend + ' ' + (index + 1)
68
68
  }.bind(this))
69
69
 
70
- this.module.querySelector('.js-add-another__remove-button').classList.toggle(
71
- 'js-add-another__remove-button--hidden',
72
- this.module.querySelectorAll('.js-add-another__fieldset:not([hidden])').length === 1
73
- )
70
+ if (this.module.dataset.emptyFields === 'false') {
71
+ this.module.querySelector('.js-add-another__remove-button').classList.toggle(
72
+ 'js-add-another__remove-button--hidden',
73
+ this.module.querySelectorAll('.js-add-another__fieldset:not([hidden])').length === 1
74
+ )
75
+ }
74
76
  }
75
77
 
76
78
  AddAnother.prototype.addNewFieldset = function (event) {
@@ -95,9 +95,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
95
95
  this.$module.showConfirmationMessage()
96
96
  this.$module.cookieBannerConfirmationMessage.focus()
97
97
 
98
- if (window.GOVUK.globalBarInit) {
99
- window.GOVUK.globalBarInit.init()
100
- }
101
98
  if (!window.GOVUK.useSingleConsentApi) {
102
99
  window.GOVUK.triggerEvent(window, 'cookie-consent')
103
100
  }
@@ -0,0 +1,62 @@
1
+ //= require govuk_publishing_components/lib/cookie-functions
2
+ window.GOVUK = window.GOVUK || {}
3
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
4
+
5
+ (function (Modules) {
6
+ function GlobalBanner ($module) {
7
+ this.$module = $module
8
+ this.GLOBAL_BANNER_SEEN_COOKIE = 'global_banner_seen'
9
+ this.alwaysOn = this.$module.getAttribute('data-global-banner-permanent') === 'true'
10
+ this.bannerVersion = parseInt(this.$module.getAttribute('data-banner-version'))
11
+ }
12
+
13
+ GlobalBanner.prototype.init = function () {
14
+ // if no cookie consent just show the banner
15
+ // if there is cookie consent...
16
+ // if there's no global banner cookie or the banner should always be shown, set the cookie and show the banner
17
+ // if there is a global banner cookie, check to see if the version number matches
18
+ // if it doesn't, set the global banner cookie and count to zero, show the banner
19
+ // if it does, check the count, if less than 3 increment, show the banner
20
+ var cookieCategory = window.GOVUK.getCookieCategory(this.GLOBAL_BANNER_SEEN_COOKIE)
21
+ var cookieConsent = window.GOVUK.getConsentCookie()
22
+
23
+ if (cookieConsent && cookieConsent[cookieCategory]) {
24
+ var currentCookie = window.GOVUK.getCookie(this.GLOBAL_BANNER_SEEN_COOKIE)
25
+
26
+ if (currentCookie === null) {
27
+ this.setBannerCookie(0)
28
+ this.makeBannerVisible()
29
+ } else {
30
+ var currentCookieContents = JSON.parse(currentCookie)
31
+ var currentCookieVersion = currentCookieContents.version
32
+
33
+ if (currentCookieVersion !== this.bannerVersion) {
34
+ this.setBannerCookie(0)
35
+ this.makeBannerVisible()
36
+ } else {
37
+ var count = currentCookieContents.count
38
+ if (this.alwaysOn) {
39
+ this.makeBannerVisible()
40
+ } else if (count < 3) {
41
+ this.setBannerCookie(count + 1)
42
+ this.makeBannerVisible()
43
+ }
44
+ }
45
+ }
46
+ } else {
47
+ this.makeBannerVisible()
48
+ }
49
+ }
50
+
51
+ GlobalBanner.prototype.setBannerCookie = function (count) {
52
+ var value = JSON.stringify({ count: count, version: this.bannerVersion })
53
+ window.GOVUK.setCookie(this.GLOBAL_BANNER_SEEN_COOKIE, value, { days: 84 })
54
+ }
55
+
56
+ GlobalBanner.prototype.makeBannerVisible = function () {
57
+ this.$module.classList.add('gem-c-global-banner--visible')
58
+ this.$module.setAttribute('data-ga4-global-banner', '')
59
+ }
60
+
61
+ Modules.GlobalBanner = GlobalBanner
62
+ })(window.GOVUK.Modules)
@@ -22,7 +22,7 @@
22
22
  govuk_contact_referrer: 'essential',
23
23
  multivariatetest_cohort_coronavirus_extremely_vulnerable_rate_limit: 'essential',
24
24
  dgu_beta_banner_dismissed: 'settings',
25
- global_bar_seen: 'settings',
25
+ global_banner_seen: 'settings',
26
26
  user_nation: 'settings',
27
27
  'JS-Detection': 'usage',
28
28
  TLSversion: 'usage',
@@ -336,7 +336,7 @@
336
336
  return str;
337
337
  }
338
338
 
339
- var VERSION = "4.0.28";
339
+ var VERSION = "4.0.29";
340
340
  /**
341
341
  * Returns the version of the script as a float to be stored in legacy systems that do not support
342
342
  * string versions.
@@ -626,36 +626,36 @@
626
626
  try {
627
627
  if (selector &&
628
628
  (node.nodeType === 9 || selector.length > MAX_SELECTOR_LENGTH || !node.parentNode)) {
629
- // Final selector.
630
- return selector;
631
- }
632
- var el = node;
633
- // Our first preference is to use the data-sctrack attribute from anywhere in the tree
634
- var trackId = getClosestScTrackAttribute(el);
635
- if (trackId) {
636
- return trackId;
637
- }
638
- if (el.id) {
639
- // Once we've found an element with ID we return the selector.
640
- return "#" + el.id + (selector ? ">" + selector : "");
641
- }
642
- else if (el) {
643
- // Otherwise attempt to get parent elements recursively
644
- var name_1 = el.nodeType === 1 ? el.nodeName.toLowerCase() : el.nodeName.toUpperCase();
645
- var classes = el.className ? "." + el.className.replace(/\s+/g, ".") : "";
646
- // Remove classes until the selector is short enough
647
- while ((name_1 + classes).length > MAX_SELECTOR_LENGTH) {
648
- classes = classes.split(".").slice(0, -1).join(".");
649
- }
650
- var currentSelector = name_1 + classes + (selector ? ">" + selector : "");
651
- if (el.parentNode) {
652
- var selectorWithParent = getNodeSelector(el.parentNode, currentSelector);
653
- if (selectorWithParent.length < MAX_SELECTOR_LENGTH) {
654
- return selectorWithParent;
629
+ // Final selector.
630
+ return selector;
631
+ }
632
+ var el = node;
633
+ // Our first preference is to use the data-sctrack attribute from anywhere in the tree
634
+ var trackId = getClosestScTrackAttribute(el);
635
+ if (trackId) {
636
+ return trackId;
637
+ }
638
+ if (el.id) {
639
+ // Once we've found an element with ID we return the selector.
640
+ return "#" + el.id + (selector ? ">" + selector : "");
641
+ }
642
+ else if (el) {
643
+ // Otherwise attempt to get parent elements recursively
644
+ var name_1 = el.nodeType === 1 ? el.nodeName.toLowerCase() : el.nodeName.toUpperCase();
645
+ var classes = el.className ? "." + el.className.replace(/\s+/g, ".") : "";
646
+ // Remove classes until the selector is short enough
647
+ while ((name_1 + classes).length > MAX_SELECTOR_LENGTH) {
648
+ classes = classes.split(".").slice(0, -1).join(".");
655
649
  }
650
+ var currentSelector = name_1 + classes + (selector ? ">" + selector : "");
651
+ if (el.parentNode) {
652
+ var selectorWithParent = getNodeSelector(el.parentNode, currentSelector);
653
+ if (selectorWithParent.length < MAX_SELECTOR_LENGTH) {
654
+ return selectorWithParent;
655
+ }
656
+ }
657
+ return currentSelector;
656
658
  }
657
- return currentSelector;
658
- }
659
659
  }
660
660
  catch (error) {
661
661
  // Do nothing.
@@ -1963,7 +1963,7 @@
1963
1963
  ].join("");
1964
1964
  }
1965
1965
  function getCustomerId() {
1966
- return String(_thisCustomerId) || "";
1966
+ return String(_thisCustomerId);
1967
1967
  }
1968
1968
  function avgDomDepth() {
1969
1969
  var aElems = document.getElementsByTagName("*");
@@ -0,0 +1,38 @@
1
+ @import "govuk_publishing_components/individual_component_support";
2
+
3
+ .gem-c-global-banner {
4
+ background-color: #d9e7f2;
5
+ border-top: govuk-spacing(2) solid govuk-colour("blue");
6
+ display: none;
7
+ @include govuk-font(19);
8
+
9
+ .govuk-link,
10
+ .govuk-link:link {
11
+ color: govuk-colour("black");
12
+ }
13
+ }
14
+
15
+ .gem-c-global-banner--visible {
16
+ display: block;
17
+ }
18
+
19
+ .gem-c-global-banner__message {
20
+ margin-bottom: 0;
21
+ margin-top: 0;
22
+ padding: govuk-spacing(4) 0;
23
+ }
24
+
25
+ .gem-c-global-banner__title {
26
+ font-weight: 700;
27
+ margin-right: govuk-spacing(2);
28
+ margin-bottom: govuk-spacing(1);
29
+
30
+ &:only-child {
31
+ margin: 0;
32
+ }
33
+ }
34
+
35
+ .gem-c-global-banner__title,
36
+ .gem-c-global-banner__text {
37
+ color: govuk-colour("black");
38
+ }
@@ -5,16 +5,13 @@
5
5
  background-color: govuk-colour("blue");
6
6
  color: govuk-colour("white");
7
7
  margin-bottom: govuk-spacing(6);
8
- padding: 0 govuk-spacing(6) govuk-spacing(6);
8
+ padding: govuk-spacing(3) govuk-spacing(6) govuk-spacing(6) govuk-spacing(6);
9
9
  box-sizing: border-box;
10
10
  }
11
11
 
12
- .gem-c-inverse-header .gem-c-inverse-header__supplement,
13
- .gem-c-inverse-header .publication-header__last-changed {
12
+ .gem-c-inverse-header__subtext {
14
13
  color: govuk-colour("white");
15
14
  margin: 0;
16
- // This publication-header class is injected on publication pages, really
17
- // it should be a component class or be a component in it's own right.
18
15
  @include govuk-font($size: 16, $line-height: 1.5);
19
16
  }
20
17
 
@@ -24,10 +21,6 @@
24
21
  padding-bottom: govuk-spacing(3);
25
22
  }
26
23
 
27
- .gem-c-inverse-header--padding-top {
28
- padding-top: govuk-spacing(3);
29
- }
30
-
31
24
  @include govuk-media-query($media-type: print) {
32
25
  .gem-c-inverse-header {
33
26
  background: none;
@@ -1,5 +1,11 @@
1
1
  @import "govuk_publishing_components/individual_component_support";
2
2
 
3
+ .gem-c-title {
4
+ @include govuk-media-query($from: tablet) {
5
+ padding-top: govuk-spacing(8);
6
+ }
7
+ }
8
+
3
9
  .gem-c-title--inverse {
4
10
  color: govuk-colour("white");
5
11
 
@@ -5,7 +5,13 @@
5
5
  %>
6
6
 
7
7
  <% content_for :title, "Component audit" %>
8
- <%= render 'govuk_publishing_components/components/title', title: "Components audit", margin_top: 0; %>
8
+ <%= render 'govuk_publishing_components/components/heading', {
9
+ text: "Components audit",
10
+ heading_level: 1,
11
+ font_size: "xl",
12
+ margin_bottom: 8
13
+ }
14
+ %>
9
15
 
10
16
  <% applications = capture do %>
11
17
  <%= render "applications" %>
@@ -5,7 +5,14 @@
5
5
  <% end %>
6
6
  <% end %>
7
7
 
8
- <%= render 'govuk_publishing_components/components/title', title: @component_example.name, context: "#{@component_doc.name} example", margin_top: 0 %>
8
+ <%= render 'govuk_publishing_components/components/heading', {
9
+ text: @component_example.name,
10
+ context: "#{@component_doc.name} example",
11
+ heading_level: 1,
12
+ font_size: "xl",
13
+ margin_bottom: 8
14
+ }
15
+ %>
9
16
 
10
17
  <% code_example = capture do %>
11
18
  <%= render partial: "govuk_publishing_components/component_guide/component_doc/call", locals: { component_doc: @component_doc, example: @component_example } %>
@@ -1,4 +1,10 @@
1
- <%= render 'govuk_publishing_components/components/title', title: GovukPublishingComponents::Config.component_guide_title, margin_top: 0 %>
1
+ <%= render 'govuk_publishing_components/components/heading', {
2
+ text: GovukPublishingComponents::Config.component_guide_title,
3
+ heading_level: 1,
4
+ font_size: "xl",
5
+ margin_bottom: 8
6
+ }
7
+ %>
2
8
 
3
9
  <div class="component-markdown">
4
10
  <p>Components are packages of template, style, behaviour and documentation that live in your application.</p>
@@ -5,7 +5,14 @@
5
5
  <% end %>
6
6
  <% end %>
7
7
 
8
- <%= render 'govuk_publishing_components/components/title', title: @component_doc.name, context: "Component", margin_top: 0; %>
8
+ <%= render 'govuk_publishing_components/components/heading', {
9
+ text: @component_doc.name,
10
+ context: "Component",
11
+ heading_level: 1,
12
+ font_size: "xl",
13
+ margin_bottom: 8
14
+ }
15
+ %>
9
16
 
10
17
  <div class="component-show">
11
18
  <div class="govuk-grid-row">
@@ -4,19 +4,27 @@
4
4
  empty ||= ""
5
5
  fieldset_legend ||= ""
6
6
  add_button_text ||= "Add another"
7
+ empty_fields ||= false
7
8
  %>
8
9
 
9
- <div data-module="add-another" class="gem-c-add-another" data-add-button-text="<%= add_button_text %>" data-fieldset-legend="<%= fieldset_legend %>">
10
- <% items.each_with_index do |item, index| %>
11
- <%= render "govuk_publishing_components/components/fieldset", {
12
- classes: "js-add-another__fieldset",
13
- legend_text: "#{fieldset_legend} #{index + 1}",
14
- heading_size: "m"
15
- } do %>
16
- <div class="js-add-another__destroy-checkbox">
17
- <%= item[:destroy_checkbox] %>
18
- </div>
19
- <%= item[:fields] %>
10
+ <%= tag.div class: "gem-c-add-another", data: {
11
+ module: "add-another",
12
+ "add-button-text": add_button_text,
13
+ "fieldset-legend": fieldset_legend,
14
+ "empty-fields": empty_fields
15
+ } do %>
16
+ <% unless empty_fields && items.count == 0 %>
17
+ <% items.each_with_index do |item, index| %>
18
+ <%= render "govuk_publishing_components/components/fieldset", {
19
+ classes: "js-add-another__fieldset",
20
+ legend_text: "#{fieldset_legend} #{index + 1}",
21
+ heading_size: "m"
22
+ } do %>
23
+ <div class="js-add-another__destroy-checkbox">
24
+ <%= item[:destroy_checkbox] %>
25
+ </div>
26
+ <%= item[:fields] %>
27
+ <% end %>
20
28
  <% end %>
21
29
  <% end %>
22
30
  <%= render "govuk_publishing_components/components/fieldset", {
@@ -26,4 +34,4 @@
26
34
  } do %>
27
35
  <%= empty %>
28
36
  <% end %>
29
- </div>
37
+ <% end %>
@@ -0,0 +1,43 @@
1
+ <%
2
+ add_gem_component_stylesheet("global-banner")
3
+
4
+ title ||= nil
5
+ title_href ||= nil
6
+ text ||= nil
7
+ banner_version ||= nil
8
+ always_visible ||= false # if true banner is always visible & does not disappear automatically after 3 pageviews
9
+
10
+ component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
11
+ component_helper.add_class("gem-c-global-banner govuk-!-display-none-print")
12
+ component_helper.set_id("global-banner")
13
+ component_helper.add_data_attribute({ module: "global-banner", nosnippet: "" })
14
+ component_helper.add_data_attribute({ banner_version: banner_version }) if banner_version
15
+ component_helper.add_data_attribute({ global_banner_permanent: true }) if always_visible
16
+
17
+ title_classes = %w(gem-c-global-banner__title)
18
+ title_classes << "js-call-to-action" if title_href
19
+ title_classes << "govuk-link govuk-link--no-visited-state" if title_href
20
+
21
+ ga4_data = {
22
+ event_name: "navigation",
23
+ type: "global bar",
24
+ section: title,
25
+ }.to_json
26
+ %>
27
+ <% if title && banner_version %>
28
+ <%= tag.div(**component_helper.all_attributes) do %>
29
+ <p class="gem-c-global-banner__message govuk-width-container">
30
+ <% if title_href %>
31
+ <a class="<%= title_classes.join(' ') %>" href="<%= title_href %>" data-module="ga4-link-tracker" data-ga4-link="<%= ga4_data %>"><%= title %></a>
32
+ <% else %>
33
+ <span class="<%= title_classes.join(' ') %>"><%= title %></span>
34
+ <% end %>
35
+
36
+ <% if text %>
37
+ <span class="gem-c-global-banner__text">
38
+ <%= text %>
39
+ </span>
40
+ <% end %>
41
+ </p>
42
+ <% end %>
43
+ <% end %>
@@ -1,14 +1,20 @@
1
1
  <%
2
2
  add_gem_component_stylesheet("inverse-header")
3
3
 
4
+ padding_top ||= nil
5
+ padding_bottom ||= nil
6
+ subtext ||= nil
7
+
4
8
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
5
9
  component_helper.add_class("gem-c-inverse-header")
6
10
  component_helper.add_class("gem-c-inverse-header--full-width") if local_assigns[:full_width]
7
- component_helper.add_class("gem-c-inverse-header--padding-top") unless local_assigns[:padding_top].eql?(false)
11
+ component_helper.add_class("govuk-!-padding-top-#{padding_top}") if [*0..9].include?(padding_top)
12
+ component_helper.add_class("govuk-!-padding-bottom-#{padding_bottom}") if [*0..9].include?(padding_bottom)
8
13
  %>
9
14
  <% block = yield %>
10
15
  <% unless block.empty? %>
11
16
  <%= tag.header(**component_helper.all_attributes) do %>
12
17
  <%= block %>
18
+ <%= content_tag(:p, subtext, class: "gem-c-inverse-header__subtext") if subtext %>
13
19
  <% end %>
14
20
  <% end %>
@@ -5,7 +5,7 @@
5
5
  emergency_banner ||= nil
6
6
  full_width ||= false
7
7
  blue_bar ||= local_assigns.include?(:blue_bar) ? local_assigns[:blue_bar] : !full_width
8
- global_bar ||= nil
8
+ global_banner ||= nil
9
9
  html_lang ||= "en"
10
10
  homepage ||= false
11
11
  layout_helper = GovukPublishingComponents::Presenters::PublicLayoutHelper.new(local_assigns)
@@ -49,10 +49,10 @@
49
49
  # height, making the two blue bars overlap and appear as one. The class is added
50
50
  # when a) there's content for the emergency or global banner *and* b) when using
51
51
  # the contrained width layout.
52
- blue_bar_dedupe = !full_width && global_bar.present?
52
+ blue_bar_dedupe = !full_width && global_banner.present?
53
53
  body_css_classes = %w(gem-c-layout-for-public govuk-template__body)
54
54
  body_css_classes << "draft" if draft_watermark
55
- body_css_classes << "global-bar-present" if global_bar.present?
55
+ body_css_classes << "global-banner-present" if global_banner.present?
56
56
 
57
57
  blue_bar_wrapper_classes = %w()
58
58
  blue_bar_wrapper_classes << "gem-c-layout-for-public__blue-bar-wrapper--#{blue_bar_background_colour}" if blue_bar_background_colour
@@ -137,17 +137,17 @@
137
137
 
138
138
  <%= raw(emergency_banner) %>
139
139
 
140
- <% if (blue_bar && !global_bar.present? && !homepage) || (blue_bar_dedupe) %>
140
+ <% if (blue_bar && !global_banner.present? && !homepage) || (blue_bar_dedupe) %>
141
141
  <%= content_tag(:div, class: blue_bar_wrapper_classes) do %>
142
142
  <div class="gem-c-layout-for-public__blue-bar govuk-width-container"></div>
143
143
  <% end %>
144
144
  <% end %>
145
145
 
146
- <% if global_bar.present? %>
146
+ <% if global_banner.present? %>
147
147
  <%= content_tag("div", {
148
148
  class: blue_bar_dedupe ? "gem-c-layout-for-public__global-banner-wrapper" : nil,
149
149
  }) do %>
150
- <%= raw(global_bar) %>
150
+ <%= raw(global_banner) %>
151
151
  <% end %>
152
152
  <% end %>
153
153
 
@@ -8,20 +8,17 @@
8
8
  context_inside ||= false
9
9
 
10
10
  inverse ||= false
11
- local_assigns[:margin_top] ||= 8
12
11
  local_assigns[:margin_bottom] ||= 8
13
12
 
14
13
  shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
15
14
 
16
15
  classes = %w[gem-c-title]
17
16
  classes << "gem-c-title--inverse" if inverse
18
- classes << shared_helper.get_margin_top
19
17
  classes << shared_helper.get_margin_bottom
20
18
 
21
19
  heading_classes = %w[gem-c-title__text]
22
20
  heading_classes << (average_title_length.present? ? 'govuk-heading-l' : 'govuk-heading-xl')
23
21
  %>
24
-
25
22
  <% @context_block = capture do %>
26
23
  <span class="govuk-caption-xl gem-c-title__context" <%= "lang=#{context_locale}" if context_locale.present? %>>
27
24
  <%= context %>
@@ -46,3 +46,15 @@ examples:
46
46
  <label for="person_1_name" class="gem-c-label govuk-label">Full name</label>
47
47
  <input class="gem-c-input govuk-input" id="person_1_name" name="person[1]name">
48
48
  </div>
49
+ start_empty:
50
+ description: By default no form fields are displayed when the component loads if no content is specified
51
+ data:
52
+ fieldset_legend: "Employee"
53
+ add_button_text: "Add an employee"
54
+ empty_fields: true
55
+ items: null
56
+ empty:
57
+ <div class="govuk-form-group">
58
+ <label for="employee_1_name" class="gem-c-label govuk-label">Full name</label>
59
+ <input class="gem-c-input govuk-input" id="employee_1_name" name="employee[1]name">
60
+ </div>
@@ -147,3 +147,12 @@ examples:
147
147
  data:
148
148
  text: Button
149
149
  aria_describedby: with_aria_describedby
150
+ with_form_attribute:
151
+ description: |
152
+ Buttons will usually be contained within their containing form, but sometimes it is desirable to have the button
153
+ outside the form with the `form` attribute pointing to the ID of the form. See
154
+ [The Mozilla dev docs on a button's `form` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#form)
155
+ for more information.
156
+ data:
157
+ text: With `form` argument
158
+ form: some_form_id
@@ -0,0 +1,30 @@
1
+ name: Global banner
2
+ description: A site-wide banner used to convey important information
3
+ body: |
4
+ If a user has consented to cookies the banner will disappear after three page views, unless the `always_visible` option is used. If no cookie consent is given the banner is always shown.
5
+
6
+ The [dev docs](https://docs.publishing.service.gov.uk/manual/global-banner.html) contains further information about this component and when it should be used.
7
+ shared_accessibility_criteria:
8
+ - link
9
+ examples:
10
+ default:
11
+ data:
12
+ title: Bring photo ID to vote
13
+ banner_version: 1
14
+ with_a_link:
15
+ data:
16
+ title: Bring photo ID to vote
17
+ title_href: "https://www.gov.uk"
18
+ banner_version: 1
19
+ with_a_link_and_text:
20
+ data:
21
+ title: Bring photo ID to vote
22
+ title_href: "https://www.gov.uk"
23
+ text: Check what photo ID you'll need to vote in person in the General Election on 4 July.
24
+ banner_version: 1
25
+ always_visible:
26
+ description: With this option set the banner appears regardless of how many times it has been seen before.
27
+ data:
28
+ title: Bring photo ID to vote
29
+ banner_version: 1
30
+ always_visible: true
@@ -1,7 +1,7 @@
1
1
  name: Inverse header
2
2
  description: A wrapper to contain header content in white text
3
3
  body: |
4
- This component can be passed a block of template code and will wrap it in a blue header. This is as light-touch as possible and doesn't attempt to deal with the margins and paddings of its content. White text is enforced on content and would need to be overridden where unwanted. Implemented to accommodate topic and list page headings but unopinionated about its contents.
4
+ This component can be passed a block of template code and will wrap it in a blue header. White text is enforced on content and would need to be overridden where unwanted. Implemented to accommodate topic and list page headings but unopinionated about its contents.
5
5
 
6
6
  If passing links to the block make sure to add [the inverse modifier](https://design-system.service.gov.uk/styles/links/#links-on-dark-backgrounds).
7
7
  uses_component_wrapper_helper: true
@@ -19,6 +19,19 @@ examples:
19
19
  inverse: true
20
20
  } %>
21
21
  <!-- end of example content -->
22
+ with_custom_padding:
23
+ description: Custom padding can be applied as shown, using the [Design System spacing scale](https://design-system.service.gov.uk/styles/spacing/).
24
+ data:
25
+ padding_top: 6
26
+ padding_bottom: 1
27
+ block: |
28
+ <!-- example content -->
29
+ <%= render "govuk_publishing_components/components/heading", {
30
+ text: "Education, Training and Skills",
31
+ inverse: true,
32
+ margin_bottom: 0
33
+ } %>
34
+ <!-- end of example content -->
22
35
  for_full_page_width:
23
36
  description: "Used when the header covers the full width of the page, but it's content is in the grid layout. The left-right padding is removed to make the contents line up with the other items on the page."
24
37
  data:
@@ -30,6 +43,17 @@ examples:
30
43
  inverse: true
31
44
  } %>
32
45
  <!-- end of example content -->
46
+ with_subtext:
47
+ data:
48
+ subtext: This is some text
49
+ block: |
50
+ <!-- example content -->
51
+ <%= render "govuk_publishing_components/components/heading", {
52
+ text: "Education, Training and Skills",
53
+ inverse: true,
54
+ margin_bottom: 0
55
+ } %>
56
+ <!-- end of example content -->
33
57
  html_publication_header:
34
58
  description: "The inverse header component is used on HTML publications. [See example on GOV.UK here](https://www.gov.uk/government/publications/ln5-0at-jackson-homes-scopwick-ltd-environmental-permit-application-advertisement/ln5-0at-jackson-homes-scopwick-ltd-environmental-permit-application)"
35
59
  data:
@@ -73,7 +73,7 @@ examples:
73
73
  with_global_banner:
74
74
  description: This allows the HTML for the global banner to be added to the page. This is only the slot for the global banner - the markup for the banner needs to be passed in.
75
75
  data:
76
- global_bar: <div class="govuk-!-padding-top-5 govuk-!-padding-bottom-3">This is the global bar slot</div>
76
+ global_banner: <div class="govuk-!-padding-top-5 govuk-!-padding-bottom-3">This is the global banner slot</div>
77
77
  with_emergency_banner:
78
78
  description: This allows the HTML for the emergency banner to be added to the page in the correct place. This is only the slot for the emergency banner - the markup for the banner needs to be passed in.
79
79
  data:
@@ -82,7 +82,7 @@ examples:
82
82
  description: Both global banner and emergency banner should be usable together.
83
83
  data:
84
84
  emergency_banner: <div class="govuk-!-padding-top-3 govuk-!-padding-bottom-3">This is the emergency banner slot</div>
85
- global_bar: <div class="govuk-!-padding-top-5 govuk-!-padding-bottom-3">This is the global bar slot</div>
85
+ global_banner: <div class="govuk-!-padding-top-5 govuk-!-padding-bottom-3">This is the global banner slot</div>
86
86
  with_account_layout_enabled:
87
87
  description: Adds account layout wrapper around the content passed in to the component
88
88
  data:
@@ -62,13 +62,3 @@ examples:
62
62
  margin_bottom: 0
63
63
  context:
64
64
  dark_background: true
65
- using_design_system_template:
66
- description: |
67
- This option allows the removal of top margin from the component so that it works within a [Design System page template](https://design-system.service.gov.uk/styles/page-template/default/index.html), where spacing above the title is already provided by padding on the wrapping div.
68
- embed: |
69
- <main class="govuk-main-wrapper">
70
- <%= component %>
71
- </main>
72
- data:
73
- title: My page title
74
- margin_top: 0
@@ -25,7 +25,8 @@ module GovukPublishingComponents
25
25
  :classes,
26
26
  :aria_label,
27
27
  :aria_controls,
28
- :aria_describedby
28
+ :aria_describedby,
29
+ :form
29
30
 
30
31
  def initialize(local_assigns)
31
32
  @disable_ga4 = local_assigns[:disable_ga4]
@@ -58,6 +59,7 @@ module GovukPublishingComponents
58
59
  @button_id = "button-id-#{SecureRandom.hex(4)}"
59
60
  @aria_controls = local_assigns[:aria_controls]
60
61
  @aria_describedby = local_assigns[:aria_describedby]
62
+ @form = local_assigns[:form]
61
63
 
62
64
  if local_assigns.include?(:classes)
63
65
  @classes = local_assigns[:classes].split(" ")
@@ -106,6 +108,7 @@ module GovukPublishingComponents
106
108
  options[:aria][:controls] = aria_controls if aria_controls
107
109
  options[:aria][:describedby] = aria_describedby if aria_describedby
108
110
  options[:draggable] = false if link?
111
+ options[:form] = form if form
109
112
  options
110
113
  end
111
114
 
@@ -1,11 +1,10 @@
1
1
  module GovukPublishingComponents
2
2
  module Presenters
3
3
  class SharedHelper
4
- attr_reader :options, :margin_top, :margin_bottom, :heading_level, :classes
4
+ attr_reader :options, :margin_bottom, :heading_level, :classes
5
5
 
6
6
  def initialize(local_assigns)
7
7
  @options = local_assigns
8
- @margin_top = @options[:margin_top] || nil
9
8
  @margin_bottom = @options[:margin_bottom] || 3
10
9
  @heading_level = @options[:heading_level] || 2
11
10
 
@@ -17,10 +16,6 @@ module GovukPublishingComponents
17
16
  end
18
17
  end
19
18
 
20
- def get_margin_top
21
- [*0..9].include?(@margin_top) ? "govuk-!-margin-top-#{margin_top}" : ""
22
- end
23
-
24
19
  def get_margin_bottom
25
20
  [*0..9].include?(@margin_bottom) ? "govuk-!-margin-bottom-#{margin_bottom}" : "govuk-!-margin-bottom-3"
26
21
  end
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "50.0.1".freeze
2
+ VERSION = "51.1.0".freeze
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 50.0.1
4
+ version: 51.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-23 00:00:00.000000000 Z
10
+ date: 2025-01-30 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: govuk_app_config
@@ -472,6 +472,7 @@ files:
472
472
  - app/assets/javascripts/govuk_publishing_components/components/cross-service-header.js
473
473
  - app/assets/javascripts/govuk_publishing_components/components/error-summary.js
474
474
  - app/assets/javascripts/govuk_publishing_components/components/feedback.js
475
+ - app/assets/javascripts/govuk_publishing_components/components/global-banner.js
475
476
  - app/assets/javascripts/govuk_publishing_components/components/govspeak.js
476
477
  - app/assets/javascripts/govuk_publishing_components/components/image-card.js
477
478
  - app/assets/javascripts/govuk_publishing_components/components/intervention.js
@@ -545,6 +546,7 @@ files:
545
546
  - app/assets/stylesheets/govuk_publishing_components/components/_fieldset.scss
546
547
  - app/assets/stylesheets/govuk_publishing_components/components/_file-upload.scss
547
548
  - app/assets/stylesheets/govuk_publishing_components/components/_glance-metric.scss
549
+ - app/assets/stylesheets/govuk_publishing_components/components/_global-banner.scss
548
550
  - app/assets/stylesheets/govuk_publishing_components/components/_govspeak-html-publication.scss
549
551
  - app/assets/stylesheets/govuk_publishing_components/components/_govspeak.scss
550
552
  - app/assets/stylesheets/govuk_publishing_components/components/_heading.scss
@@ -686,6 +688,7 @@ files:
686
688
  - app/views/govuk_publishing_components/components/_fieldset.html.erb
687
689
  - app/views/govuk_publishing_components/components/_file_upload.html.erb
688
690
  - app/views/govuk_publishing_components/components/_glance_metric.html.erb
691
+ - app/views/govuk_publishing_components/components/_global_banner.html.erb
689
692
  - app/views/govuk_publishing_components/components/_google_tag_manager_script.html.erb
690
693
  - app/views/govuk_publishing_components/components/_govspeak.html.erb
691
694
  - app/views/govuk_publishing_components/components/_govspeak_html_publication.html.erb
@@ -781,6 +784,7 @@ files:
781
784
  - app/views/govuk_publishing_components/components/docs/fieldset.yml
782
785
  - app/views/govuk_publishing_components/components/docs/file_upload.yml
783
786
  - app/views/govuk_publishing_components/components/docs/glance_metric.yml
787
+ - app/views/govuk_publishing_components/components/docs/global_banner.yml
784
788
  - app/views/govuk_publishing_components/components/docs/google_tag_manager_script.yml
785
789
  - app/views/govuk_publishing_components/components/docs/govspeak.yml
786
790
  - app/views/govuk_publishing_components/components/docs/govspeak_html_publication.yml