govuk_publishing_components 29.7.0 → 29.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics/explicit-cross-domain-links.js +72 -73
  3. data/app/assets/javascripts/govuk_publishing_components/analytics/page-content.js +13 -2
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-click-tracking.js +49 -0
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  6. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +0 -1
  7. data/app/assets/javascripts/govuk_publishing_components/modules.js +0 -1
  8. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-measurer.js +37 -0
  9. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +166 -142
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_cards.scss +11 -4
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_contextual-sidebar.scss +20 -0
  12. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +3 -8
  13. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +8 -2
  14. data/app/controllers/govuk_publishing_components/audit_controller.rb +3 -2
  15. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +0 -9
  16. data/app/models/govuk_publishing_components/audit_comparer.rb +92 -34
  17. data/app/views/govuk_publishing_components/audit/_applications.html.erb +20 -9
  18. data/app/views/govuk_publishing_components/component_guide/index.html.erb +3 -21
  19. data/app/views/govuk_publishing_components/component_guide/show.html.erb +1 -1
  20. data/app/views/govuk_publishing_components/components/_cards.html.erb +13 -11
  21. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +20 -2
  22. data/app/views/govuk_publishing_components/components/_summary_list.html.erb +4 -5
  23. data/app/views/govuk_publishing_components/components/contextual_sidebar/_ukraine_cta.html.erb +18 -19
  24. data/app/views/govuk_publishing_components/components/docs/contents_list.yml +1 -1
  25. data/app/views/govuk_publishing_components/components/docs/document_list.yml +4 -4
  26. data/app/views/govuk_publishing_components/components/docs/heading.yml +1 -1
  27. data/app/views/govuk_publishing_components/components/docs/image_card.yml +1 -1
  28. data/app/views/govuk_publishing_components/components/docs/meta_tags.yml +4 -4
  29. data/app/views/govuk_publishing_components/components/docs/metadata.yml +1 -1
  30. data/app/views/govuk_publishing_components/components/docs/share_links.yml +1 -1
  31. data/app/views/govuk_publishing_components/components/docs/subscription_links.yml +1 -1
  32. data/app/views/govuk_publishing_components/components/docs/translation_nav.yml +1 -2
  33. data/config/locales/ar.yml +1 -2
  34. data/config/locales/az.yml +1 -2
  35. data/config/locales/be.yml +1 -2
  36. data/config/locales/bg.yml +1 -2
  37. data/config/locales/bn.yml +1 -2
  38. data/config/locales/cs.yml +1 -2
  39. data/config/locales/cy.yml +1 -2
  40. data/config/locales/da.yml +1 -2
  41. data/config/locales/de.yml +1 -2
  42. data/config/locales/dr.yml +1 -2
  43. data/config/locales/el.yml +1 -2
  44. data/config/locales/en.yml +9 -2
  45. data/config/locales/es-419.yml +1 -2
  46. data/config/locales/es.yml +1 -2
  47. data/config/locales/et.yml +1 -2
  48. data/config/locales/fa.yml +1 -2
  49. data/config/locales/fi.yml +1 -2
  50. data/config/locales/fr.yml +1 -2
  51. data/config/locales/gd.yml +1 -2
  52. data/config/locales/gu.yml +1 -2
  53. data/config/locales/he.yml +1 -2
  54. data/config/locales/hi.yml +1 -2
  55. data/config/locales/hr.yml +1 -2
  56. data/config/locales/hu.yml +1 -2
  57. data/config/locales/hy.yml +1 -2
  58. data/config/locales/id.yml +1 -2
  59. data/config/locales/is.yml +1 -2
  60. data/config/locales/it.yml +1 -2
  61. data/config/locales/ja.yml +1 -2
  62. data/config/locales/ka.yml +1 -2
  63. data/config/locales/kk.yml +1 -2
  64. data/config/locales/ko.yml +1 -2
  65. data/config/locales/lt.yml +1 -2
  66. data/config/locales/lv.yml +1 -2
  67. data/config/locales/ms.yml +1 -2
  68. data/config/locales/mt.yml +1 -2
  69. data/config/locales/nl.yml +1 -2
  70. data/config/locales/no.yml +1 -2
  71. data/config/locales/pa-pk.yml +1 -2
  72. data/config/locales/pa.yml +1 -2
  73. data/config/locales/pl.yml +1 -2
  74. data/config/locales/ps.yml +1 -2
  75. data/config/locales/pt.yml +1 -2
  76. data/config/locales/ro.yml +1 -2
  77. data/config/locales/ru.yml +1 -2
  78. data/config/locales/si.yml +1 -2
  79. data/config/locales/sk.yml +1 -2
  80. data/config/locales/sl.yml +1 -2
  81. data/config/locales/so.yml +1 -2
  82. data/config/locales/sq.yml +1 -2
  83. data/config/locales/sr.yml +1 -2
  84. data/config/locales/sv.yml +1 -2
  85. data/config/locales/sw.yml +1 -2
  86. data/config/locales/ta.yml +1 -2
  87. data/config/locales/th.yml +1 -2
  88. data/config/locales/tk.yml +1 -2
  89. data/config/locales/tr.yml +1 -2
  90. data/config/locales/uk.yml +1 -2
  91. data/config/locales/ur.yml +1 -2
  92. data/config/locales/uz.yml +1 -2
  93. data/config/locales/vi.yml +1 -2
  94. data/config/locales/zh-hk.yml +1 -2
  95. data/config/locales/zh-tw.yml +1 -2
  96. data/config/locales/zh.yml +1 -2
  97. data/lib/generators/govuk_publishing_components/templates/_component.html.erb +1 -1
  98. data/lib/govuk_publishing_components/app_helpers/brand_helper.rb +1 -1
  99. data/lib/govuk_publishing_components/presenters/attachment_helper.rb +1 -3
  100. data/lib/govuk_publishing_components/presenters/public_layout_helper.rb +35 -16
  101. data/lib/govuk_publishing_components/version.rb +1 -1
  102. data/node_modules/govuk-frontend/govuk/all.js +120 -49
  103. data/node_modules/govuk-frontend/govuk/components/back-link/macro-options.json +2 -2
  104. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +0 -2
  105. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/macro-options.json +2 -2
  106. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +6 -16
  107. data/node_modules/govuk-frontend/govuk/components/button/macro-options.json +2 -2
  108. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +120 -49
  109. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +33 -17
  110. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +2 -2
  111. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +1 -4
  112. data/node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss +3 -2
  113. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +22 -10
  114. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +2 -2
  115. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +23 -23
  116. data/node_modules/govuk-frontend/govuk/components/date-input/template.njk +1 -1
  117. data/node_modules/govuk-frontend/govuk/components/details/macro-options.json +4 -4
  118. data/node_modules/govuk-frontend/govuk/components/error-message/macro-options.json +2 -2
  119. data/node_modules/govuk-frontend/govuk/components/error-summary/macro-options.json +3 -3
  120. data/node_modules/govuk-frontend/govuk/components/fieldset/macro-options.json +2 -2
  121. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +12 -22
  122. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +13 -3
  123. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +2 -2
  124. data/node_modules/govuk-frontend/govuk/components/hint/macro-options.json +2 -2
  125. data/node_modules/govuk-frontend/govuk/components/input/_index.scss +4 -13
  126. data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +5 -5
  127. data/node_modules/govuk-frontend/govuk/components/inset-text/macro-options.json +2 -2
  128. data/node_modules/govuk-frontend/govuk/components/label/macro-options.json +2 -2
  129. data/node_modules/govuk-frontend/govuk/components/panel/_index.scss +1 -1
  130. data/node_modules/govuk-frontend/govuk/components/panel/macro-options.json +4 -4
  131. data/node_modules/govuk-frontend/govuk/components/phase-banner/macro-options.json +2 -2
  132. data/node_modules/govuk-frontend/govuk/components/radios/_index.scss +5 -4
  133. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +17 -12
  134. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +2 -2
  135. data/node_modules/govuk-frontend/govuk/components/skip-link/_index.scss +1 -3
  136. data/node_modules/govuk-frontend/govuk/components/skip-link/macro-options.json +2 -2
  137. data/node_modules/govuk-frontend/govuk/components/summary-list/macro-options.json +5 -5
  138. data/node_modules/govuk-frontend/govuk/components/table/macro-options.json +4 -4
  139. data/node_modules/govuk-frontend/govuk/components/tabs/macro-options.json +2 -2
  140. data/node_modules/govuk-frontend/govuk/components/tag/macro-options.json +2 -2
  141. data/node_modules/govuk-frontend/govuk/components/warning-text/macro-options.json +2 -2
  142. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +3 -3
  143. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +7 -5
  144. data/node_modules/govuk-frontend/govuk/helpers/_media-queries.scss +2 -2
  145. data/node_modules/govuk-frontend/govuk/helpers/_shape-arrow.scss +1 -1
  146. data/node_modules/govuk-frontend/govuk/helpers/_spacing.scss +3 -3
  147. data/node_modules/govuk-frontend/govuk/helpers/_typography.scss +2 -2
  148. data/node_modules/govuk-frontend/govuk/objects/_button-group.scss +10 -26
  149. data/node_modules/govuk-frontend/govuk/objects/_template.scss +1 -1
  150. data/node_modules/govuk-frontend/govuk/objects/_width-container.scss +0 -4
  151. data/node_modules/govuk-frontend/govuk/tools/_exports.scss +1 -1
  152. data/node_modules/govuk-frontend/govuk/tools/_font-url.scss +1 -1
  153. data/node_modules/govuk-frontend/govuk/tools/_image-url.scss +1 -1
  154. data/node_modules/govuk-frontend/govuk/tools/_px-to-em.scss +2 -2
  155. data/node_modules/govuk-frontend/govuk/tools/_px-to-rem.scss +1 -1
  156. data/node_modules/govuk-frontend/govuk-esm/all.mjs +88 -0
  157. data/node_modules/govuk-frontend/govuk-esm/common.mjs +28 -0
  158. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +374 -0
  159. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +64 -0
  160. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +251 -0
  161. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +164 -0
  162. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +147 -0
  163. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +168 -0
  164. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +52 -0
  165. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +55 -0
  166. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +122 -0
  167. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +94 -0
  168. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +282 -0
  169. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/DOMTokenList.js +264 -0
  170. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Document.js +26 -0
  171. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/classList.js +93 -0
  172. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/closest.js +24 -0
  173. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/matches.js +23 -0
  174. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/nextElementSibling.js +22 -0
  175. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/previousElementSibling.js +22 -0
  176. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element.js +114 -0
  177. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Event.js +252 -0
  178. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Function/prototype/bind.js +159 -0
  179. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Object/defineProperty.js +86 -0
  180. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Window.js +20 -0
  181. data/node_modules/govuk-frontend/package.json +8 -1
  182. metadata +30 -3
@@ -162,9 +162,8 @@ pt:
162
162
  link_text: Verifique o que precisa de fazer
163
163
  title: Brexit
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: Locais mundiais
169
168
  search_box:
170
169
  input_title: Pesquisar
@@ -163,9 +163,8 @@ ro:
163
163
  link_text: Verificați ce trebuie să faceți
164
164
  title: Brexit
165
165
  ukraine:
166
- link_path:
167
- link_text:
168
166
  title:
167
+ links:
169
168
  world_locations: Locații pe glob
170
169
  search_box:
171
170
  input_title: Căutați
@@ -166,9 +166,8 @@ ru:
166
166
  link_text: Проверьте, что вам нужно сделать
167
167
  title: Брексит
168
168
  ukraine:
169
- link_path:
170
- link_text:
171
169
  title:
170
+ links:
172
171
  world_locations: Места нахождения по миру
173
172
  search_box:
174
173
  input_title: Поиск
@@ -162,9 +162,8 @@ si:
162
162
  link_text: ඔබ කළ යුතු දේ පරීක්ෂා කරන්න
163
163
  title: බ්රෙක්සිට්
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: ලෝක ස්ථාන
169
168
  search_box:
170
169
  input_title: සොයන්න
@@ -167,9 +167,8 @@ sk:
167
167
  link_text: Skontrolujte, čo je potrebné urobiť
168
168
  title: Brexit
169
169
  ukraine:
170
- link_path:
171
- link_text:
172
170
  title:
171
+ links:
173
172
  world_locations: Svetové lokality
174
173
  search_box:
175
174
  input_title: Vyhľadávanie
@@ -169,9 +169,8 @@ sl:
169
169
  link_text: Preverite, kaj morate storiti
170
170
  title: Brexit
171
171
  ukraine:
172
- link_path:
173
- link_text:
174
172
  title:
173
+ links:
175
174
  world_locations: Lokacije po svetu
176
175
  search_box:
177
176
  input_title: Iskanje
@@ -162,9 +162,8 @@ so:
162
162
  link_text: Hubi waxaad u baahantahay inaad qabato
163
163
  title: Ka bixitaanka Ingiriiska
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: Goobaha Dunida
169
168
  search_box:
170
169
  input_title: Baadh
@@ -162,9 +162,8 @@ sq:
162
162
  link_text: Kontrolloni se çfarë duhet të bëni
163
163
  title: Brexit
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: Vendndodhjet globale
169
168
  search_box:
170
169
  input_title: Kërko
@@ -163,9 +163,8 @@ sr:
163
163
  link_text: Proverite šta treba da uradite
164
164
  title: Bregzit
165
165
  ukraine:
166
- link_path:
167
- link_text:
168
166
  title:
167
+ links:
169
168
  world_locations: Globalne lokacije
170
169
  search_box:
171
170
  input_title: Pretraži
@@ -162,9 +162,8 @@ sv:
162
162
  link_text: Kontrollera vad du behöver göra
163
163
  title: Brexit
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: Platser i världen
169
168
  search_box:
170
169
  input_title: Sök på
@@ -162,9 +162,8 @@ sw:
162
162
  link_text: Angalia unachopaswa kufanya
163
163
  title: Brexit
164
164
  ukraine:
165
- link_path:
166
- link_text:
167
165
  title:
166
+ links:
168
167
  world_locations: Maeneo ya kimataifa
169
168
  search_box:
170
169
  input_title: Tafuta
@@ -163,9 +163,8 @@ ta:
163
163
  link_text: நீங்கள் செய்யவேண்டியது என்ன என்று பாருங்கள்
164
164
  title: பிரெக்சிட்
165
165
  ukraine:
166
- link_path:
167
- link_text:
168
166
  title:
167
+ links:
169
168
  world_locations: உலக இருப்பிடங்கள்
170
169
  search_box:
171
170
  input_title: தேடு
@@ -160,9 +160,8 @@ th:
160
160
  link_text: ตรวจสอบสิ่งที่คุณต้องทำ
161
161
  title: Brexit
162
162
  ukraine:
163
- link_path:
164
- link_text:
165
163
  title:
164
+ links:
166
165
  world_locations: สถานที่ทั่วโลก
167
166
  search_box:
168
167
  input_title: ค้นหา
@@ -163,9 +163,8 @@ tk:
163
163
  link_text: Näme etmelidigiňizi belläň
164
164
  title: Brexit
165
165
  ukraine:
166
- link_path:
167
- link_text:
168
166
  title:
167
+ links:
169
168
  world_locations: Dünýä ýerleri
170
169
  search_box:
171
170
  input_title: Gözlemek
@@ -163,9 +163,8 @@ tr:
163
163
  link_text: Ne yapmaya ihtiyacınız olduğunu kontrol edin
164
164
  title: Brexit
165
165
  ukraine:
166
- link_path:
167
- link_text:
168
166
  title:
167
+ links:
169
168
  world_locations: Dünya geneli konumlar
170
169
  search_box:
171
170
  input_title: Ara
@@ -169,9 +169,8 @@ uk:
169
169
  link_text: Перевірте, що вам потрібно зробити
170
170
  title: Brexit
171
171
  ukraine:
172
- link_path:
173
- link_text:
174
172
  title:
173
+ links:
175
174
  world_locations: Світові локації
176
175
  search_box:
177
176
  input_title: Пошук
@@ -159,9 +159,8 @@ ur:
159
159
  link_text: پڑتال کریں کہ آپ کو کیا کرنے کی ضرورت ہے
160
160
  title: Brexit
161
161
  ukraine:
162
- link_path:
163
- link_text:
164
162
  title:
163
+ links:
165
164
  world_locations: عالمی مقامات
166
165
  search_box:
167
166
  input_title: تلاش
@@ -164,9 +164,8 @@ uz:
164
164
  link_text: Нима қилиш зарурлигини текшириш
165
165
  title: Брексит
166
166
  ukraine:
167
- link_path:
168
- link_text:
169
167
  title:
168
+ links:
170
169
  world_locations: Жаҳондаги жойлашиш жойи
171
170
  search_box:
172
171
  input_title: Излаш
@@ -161,9 +161,8 @@ vi:
161
161
  link_text: Kiểm tra những gì bạn cần làm
162
162
  title: Brexit
163
163
  ukraine:
164
- link_path:
165
- link_text:
166
164
  title:
165
+ links:
167
166
  world_locations: Các vị trí trên thế giới
168
167
  search_box:
169
168
  input_title: Tìm kiếm
@@ -160,9 +160,8 @@ zh-hk:
160
160
  link_text: 查看您需要做的事
161
161
  title: 英國脫歐
162
162
  ukraine:
163
- link_path:
164
- link_text:
165
163
  title:
164
+ links:
166
165
  world_locations: 全世界之地點
167
166
  search_box:
168
167
  input_title: 搜尋
@@ -160,9 +160,8 @@ zh-tw:
160
160
  link_text: 確認你需要:
161
161
  title: 脫歐
162
162
  ukraine:
163
- link_path:
164
- link_text:
165
163
  title:
164
+ links:
166
165
  world_locations: 世界地點
167
166
  search_box:
168
167
  input_title: 搜尋
@@ -160,9 +160,8 @@ zh:
160
160
  link_text: 检查您需要做的事情
161
161
  title: 英国脱欧
162
162
  ukraine:
163
- link_path:
164
- link_text:
165
163
  title:
164
+ links:
166
165
  world_locations: 世界地点
167
166
  search_box:
168
167
  input_title: 搜索
@@ -1,3 +1,3 @@
1
1
  <div class="<%= @component_prefix %><%= @public_name %>">
2
- <h2><a href="https://github.com/alphagov/govuk_publishing_components/blob/master/docs/component_conventions.md">How to build a component</a></h2>
2
+ <h2><a href="https://github.com/alphagov/govuk_publishing_components/blob/main/docs/component_conventions.md">How to build a component</a></h2>
3
3
  </div>
@@ -7,7 +7,7 @@ module GovukPublishingComponents
7
7
 
8
8
  # Apply government organisation branding to individual components, specifically
9
9
  # link colour and border colour
10
- # see https://github.com/alphagov/govuk_publishing_components/blob/master/docs/component_branding.md
10
+ # see https://github.com/alphagov/govuk_publishing_components/blob/main/docs/component_branding.md
11
11
 
12
12
  def brand_class
13
13
  "brand--#{@brand}" if @brand
@@ -6,9 +6,7 @@ module GovukPublishingComponents
6
6
  # scheme is rolled out further this can be removed.
7
7
  # Currently DfE, DWP and DVSA are participating in the pilot.
8
8
  EMAILS_IN_ACCESSIBLE_FORMAT_REQUEST_PILOT = %w[govuk_publishing_components@example.com
9
- alternative.formats@education.gov.uk
10
- accessible.formats@dwp.gov.uk
11
- gov.uk.publishing@dvsa.gov.uk].freeze
9
+ alternative.formats@education.gov.uk].freeze
12
10
 
13
11
  delegate :opendocument?, :document?, :spreadsheet?, to: :content_type
14
12
 
@@ -2,7 +2,7 @@ module GovukPublishingComponents
2
2
  module Presenters
3
3
  class PublicLayoutHelper
4
4
  FOOTER_NAVIGATION_COLUMNS = [2, 1].freeze
5
-
5
+ FOOTER_TRACK_ACTIONS = %w[topicsLink governmentActivityLink].freeze
6
6
  FOOTER_META = {
7
7
  items: [
8
8
  {
@@ -46,25 +46,44 @@ module GovukPublishingComponents
46
46
  attr_reader :footer_navigation, :footer_meta, :cookie_banner_data
47
47
 
48
48
  def initialize(local_assigns)
49
- @footer_navigation = local_assigns[:footer_navigation] || I18n.t("components.layout_footer.navigation_links").each_with_index.map do |menu, i|
49
+ @footer_navigation = local_assigns[:footer_navigation] || navigation_link_generation_from_locale(I18n.t("components.layout_footer.navigation_links"))
50
+ @footer_meta = local_assigns[:footer_meta] || { items: add_data_attributes_to_links(FOOTER_META[:items], "supportLink") }
51
+ @cookie_banner_data = local_assigns[:cookie_banner_data] || {}
52
+ end
53
+
54
+ def navigation_link_generation_from_locale(links)
55
+ links.each_with_index.map do |menu, i|
50
56
  {
51
57
  title: menu[:title],
52
- columns: FOOTER_NAVIGATION_COLUMNS[i],
53
- items: menu[:menu_contents].map do |item|
54
- item.merge({
55
- attributes: {
56
- data: {
57
- track_category: "footerClicked",
58
- track_action: "footerLinks",
59
- track_label: item[:text],
60
- },
61
- },
62
- })
63
- end,
58
+ columns: footer_navigation_columns[i],
59
+ items: add_data_attributes_to_links(menu[:menu_contents], footer_track_actions[i]),
64
60
  }
65
61
  end
66
- @footer_meta = local_assigns[:footer_meta] || FOOTER_META
67
- @cookie_banner_data = local_assigns[:cookie_banner_data] || {}
62
+ end
63
+
64
+ def footer_navigation_columns
65
+ FOOTER_NAVIGATION_COLUMNS
66
+ end
67
+
68
+ def footer_track_actions
69
+ FOOTER_TRACK_ACTIONS
70
+ end
71
+
72
+ def generate_data_attribute(link, track_action)
73
+ {
74
+ track_category: "footerClicked",
75
+ track_action: track_action,
76
+ track_label: link[:href],
77
+ track_options: {
78
+ dimension29: link[:text],
79
+ },
80
+ }
81
+ end
82
+
83
+ def add_data_attributes_to_links(items, track_action)
84
+ items.map do |item|
85
+ item.deep_merge({ attributes: { data: generate_data_attribute(item, track_action) } })
86
+ end
68
87
  end
69
88
  end
70
89
  end
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "29.7.0".freeze
2
+ VERSION = "29.10.0".freeze
3
3
  end
@@ -1601,9 +1601,9 @@ Details.prototype.polyfillHandleInputs = function (node, callback) {
1601
1601
  function CharacterCount ($module) {
1602
1602
  this.$module = $module;
1603
1603
  this.$textarea = $module.querySelector('.govuk-js-character-count');
1604
- if (this.$textarea) {
1605
- this.$countMessage = document.getElementById(this.$textarea.id + '-info');
1606
- }
1604
+ this.$visibleCountMessage = null;
1605
+ this.$screenReaderCountMessage = null;
1606
+ this.lastInputTimestamp = null;
1607
1607
  }
1608
1608
 
1609
1609
  CharacterCount.prototype.defaults = {
@@ -1613,18 +1613,39 @@ CharacterCount.prototype.defaults = {
1613
1613
 
1614
1614
  // Initialize component
1615
1615
  CharacterCount.prototype.init = function () {
1616
+ // Check that required elements are present
1617
+ if (!this.$textarea) {
1618
+ return
1619
+ }
1620
+
1616
1621
  // Check for module
1617
1622
  var $module = this.$module;
1618
1623
  var $textarea = this.$textarea;
1619
- var $countMessage = this.$countMessage;
1620
-
1621
- if (!$textarea || !$countMessage) {
1622
- return
1623
- }
1624
+ var $fallbackLimitMessage = document.getElementById($textarea.id + '-info');
1624
1625
 
1625
- // We move count message right after the field
1626
+ // Move the fallback count message to be immediately after the textarea
1626
1627
  // Kept for backwards compatibility
1627
- $textarea.insertAdjacentElement('afterend', $countMessage);
1628
+ $textarea.insertAdjacentElement('afterend', $fallbackLimitMessage);
1629
+
1630
+ // Create the *screen reader* specific live-updating counter
1631
+ // This doesn't need any styling classes, as it is never visible
1632
+ var $screenReaderCountMessage = document.createElement('div');
1633
+ $screenReaderCountMessage.className = 'govuk-character-count__sr-status govuk-visually-hidden';
1634
+ $screenReaderCountMessage.setAttribute('aria-live', 'polite');
1635
+ this.$screenReaderCountMessage = $screenReaderCountMessage;
1636
+ $fallbackLimitMessage.insertAdjacentElement('afterend', $screenReaderCountMessage);
1637
+
1638
+ // Create our live-updating counter element, copying the classes from the
1639
+ // fallback element for backwards compatibility as these may have been configured
1640
+ var $visibleCountMessage = document.createElement('div');
1641
+ $visibleCountMessage.className = $fallbackLimitMessage.className;
1642
+ $visibleCountMessage.classList.add('govuk-character-count__status');
1643
+ $visibleCountMessage.setAttribute('aria-hidden', 'true');
1644
+ this.$visibleCountMessage = $visibleCountMessage;
1645
+ $fallbackLimitMessage.insertAdjacentElement('afterend', $visibleCountMessage);
1646
+
1647
+ // Hide the fallback limit message
1648
+ $fallbackLimitMessage.classList.add('govuk-visually-hidden');
1628
1649
 
1629
1650
  // Read options set using dataset ('data-' values)
1630
1651
  this.options = this.getDataset($module);
@@ -1644,23 +1665,19 @@ CharacterCount.prototype.init = function () {
1644
1665
  }
1645
1666
 
1646
1667
  // Remove hard limit if set
1647
- $module.removeAttribute('maxlength');
1668
+ $textarea.removeAttribute('maxlength');
1669
+
1670
+ this.bindChangeEvents();
1648
1671
 
1649
1672
  // When the page is restored after navigating 'back' in some browsers the
1650
1673
  // state of the character count is not restored until *after* the DOMContentLoaded
1651
- // event is fired, so we need to sync after the pageshow event in browsers
1652
- // that support it.
1674
+ // event is fired, so we need to manually update it after the pageshow event
1675
+ // in browsers that support it.
1653
1676
  if ('onpageshow' in window) {
1654
- window.addEventListener('pageshow', this.sync.bind(this));
1677
+ window.addEventListener('pageshow', this.updateCountMessage.bind(this));
1655
1678
  } else {
1656
- window.addEventListener('DOMContentLoaded', this.sync.bind(this));
1679
+ window.addEventListener('DOMContentLoaded', this.updateCountMessage.bind(this));
1657
1680
  }
1658
-
1659
- this.sync();
1660
- };
1661
-
1662
- CharacterCount.prototype.sync = function () {
1663
- this.bindChangeEvents();
1664
1681
  this.updateCountMessage();
1665
1682
  };
1666
1683
 
@@ -1695,7 +1712,7 @@ CharacterCount.prototype.count = function (text) {
1695
1712
  // Bind input propertychange to the elements and update based on the change
1696
1713
  CharacterCount.prototype.bindChangeEvents = function () {
1697
1714
  var $textarea = this.$textarea;
1698
- $textarea.addEventListener('keyup', this.checkIfValueChanged.bind(this));
1715
+ $textarea.addEventListener('keyup', this.handleKeyUp.bind(this));
1699
1716
 
1700
1717
  // Bind focus/blur events to start/stop polling
1701
1718
  $textarea.addEventListener('focus', this.handleFocus.bind(this));
@@ -1713,42 +1730,64 @@ CharacterCount.prototype.checkIfValueChanged = function () {
1713
1730
  }
1714
1731
  };
1715
1732
 
1716
- // Update message box
1733
+ // Helper function to update both the visible and screen reader-specific
1734
+ // counters simultaneously (e.g. on init)
1717
1735
  CharacterCount.prototype.updateCountMessage = function () {
1718
- var countElement = this.$textarea;
1719
- var options = this.options;
1720
- var countMessage = this.$countMessage;
1736
+ this.updateVisibleCountMessage();
1737
+ this.updateScreenReaderCountMessage();
1738
+ };
1721
1739
 
1722
- // Determine the remaining number of characters/words
1723
- var currentLength = this.count(countElement.value);
1724
- var maxLength = this.maxLength;
1725
- var remainingNumber = maxLength - currentLength;
1740
+ // Update visible counter
1741
+ CharacterCount.prototype.updateVisibleCountMessage = function () {
1742
+ var $textarea = this.$textarea;
1743
+ var $visibleCountMessage = this.$visibleCountMessage;
1744
+ var remainingNumber = this.maxLength - this.count($textarea.value);
1726
1745
 
1727
- // Set threshold if presented in options
1728
- var thresholdPercent = options.threshold ? options.threshold : 0;
1729
- var thresholdValue = maxLength * thresholdPercent / 100;
1730
- if (thresholdValue > currentLength) {
1731
- countMessage.classList.add('govuk-character-count__message--disabled');
1732
- // Ensure threshold is hidden for users of assistive technologies
1733
- countMessage.setAttribute('aria-hidden', true);
1746
+ // If input is over the threshold, remove the disabled class which renders the
1747
+ // counter invisible.
1748
+ if (this.isOverThreshold()) {
1749
+ $visibleCountMessage.classList.remove('govuk-character-count__message--disabled');
1734
1750
  } else {
1735
- countMessage.classList.remove('govuk-character-count__message--disabled');
1736
- // Ensure threshold is visible for users of assistive technologies
1737
- countMessage.removeAttribute('aria-hidden');
1751
+ $visibleCountMessage.classList.add('govuk-character-count__message--disabled');
1738
1752
  }
1739
1753
 
1740
1754
  // Update styles
1741
1755
  if (remainingNumber < 0) {
1742
- countElement.classList.add('govuk-textarea--error');
1743
- countMessage.classList.remove('govuk-hint');
1744
- countMessage.classList.add('govuk-error-message');
1756
+ $textarea.classList.add('govuk-textarea--error');
1757
+ $visibleCountMessage.classList.remove('govuk-hint');
1758
+ $visibleCountMessage.classList.add('govuk-error-message');
1759
+ } else {
1760
+ $textarea.classList.remove('govuk-textarea--error');
1761
+ $visibleCountMessage.classList.remove('govuk-error-message');
1762
+ $visibleCountMessage.classList.add('govuk-hint');
1763
+ }
1764
+
1765
+ // Update message
1766
+ $visibleCountMessage.innerHTML = this.formattedUpdateMessage();
1767
+ };
1768
+
1769
+ // Update screen reader-specific counter
1770
+ CharacterCount.prototype.updateScreenReaderCountMessage = function () {
1771
+ var $screenReaderCountMessage = this.$screenReaderCountMessage;
1772
+
1773
+ // If over the threshold, remove the aria-hidden attribute, allowing screen
1774
+ // readers to announce the content of the element.
1775
+ if (this.isOverThreshold()) {
1776
+ $screenReaderCountMessage.removeAttribute('aria-hidden');
1745
1777
  } else {
1746
- countElement.classList.remove('govuk-textarea--error');
1747
- countMessage.classList.remove('govuk-error-message');
1748
- countMessage.classList.add('govuk-hint');
1778
+ $screenReaderCountMessage.setAttribute('aria-hidden', true);
1749
1779
  }
1750
1780
 
1751
1781
  // Update message
1782
+ $screenReaderCountMessage.innerHTML = this.formattedUpdateMessage();
1783
+ };
1784
+
1785
+ // Format update message
1786
+ CharacterCount.prototype.formattedUpdateMessage = function () {
1787
+ var $textarea = this.$textarea;
1788
+ var options = this.options;
1789
+ var remainingNumber = this.maxLength - this.count($textarea.value);
1790
+
1752
1791
  var charVerb = 'remaining';
1753
1792
  var charNoun = 'character';
1754
1793
  var displayNumber = remainingNumber;
@@ -1760,12 +1799,44 @@ CharacterCount.prototype.updateCountMessage = function () {
1760
1799
  charVerb = (remainingNumber < 0) ? 'too many' : 'remaining';
1761
1800
  displayNumber = Math.abs(remainingNumber);
1762
1801
 
1763
- countMessage.innerHTML = 'You have ' + displayNumber + ' ' + charNoun + ' ' + charVerb;
1802
+ return 'You have ' + displayNumber + ' ' + charNoun + ' ' + charVerb
1803
+ };
1804
+
1805
+ // Checks whether the value is over the configured threshold for the input.
1806
+ // If there is no configured threshold, it is set to 0 and this function will
1807
+ // always return true.
1808
+ CharacterCount.prototype.isOverThreshold = function () {
1809
+ var $textarea = this.$textarea;
1810
+ var options = this.options;
1811
+
1812
+ // Determine the remaining number of characters/words
1813
+ var currentLength = this.count($textarea.value);
1814
+ var maxLength = this.maxLength;
1815
+
1816
+ // Set threshold if presented in options
1817
+ var thresholdPercent = options.threshold ? options.threshold : 0;
1818
+ var thresholdValue = maxLength * thresholdPercent / 100;
1819
+
1820
+ return (thresholdValue <= currentLength)
1821
+ };
1822
+
1823
+ // Update the visible character counter and keep track of when the last update
1824
+ // happened for each keypress
1825
+ CharacterCount.prototype.handleKeyUp = function () {
1826
+ this.updateVisibleCountMessage();
1827
+ this.lastInputTimestamp = Date.now();
1764
1828
  };
1765
1829
 
1766
1830
  CharacterCount.prototype.handleFocus = function () {
1767
- // Check if value changed on focus
1768
- this.valueChecker = setInterval(this.checkIfValueChanged.bind(this), 1000);
1831
+ // If the field is focused, and a keyup event hasn't been detected for at
1832
+ // least 1000 ms (1 second), then run the manual change check.
1833
+ // This is so that the update triggered by the manual comparison doesn't
1834
+ // conflict with debounced KeyboardEvent updates.
1835
+ this.valueChecker = setInterval(function () {
1836
+ if (!this.lastInputTimestamp || (Date.now() - 500) >= this.lastInputTimestamp) {
1837
+ this.checkIfValueChanged();
1838
+ }
1839
+ }.bind(this), 1000);
1769
1840
  };
1770
1841
 
1771
1842
  CharacterCount.prototype.handleBlur = function () {
@@ -3,13 +3,13 @@
3
3
  "name": "text",
4
4
  "type": "string",
5
5
  "required": false,
6
- "description": "Text to use within the back link component. If `html` is provided, the `text` argument will be ignored. Defaults to 'Back'."
6
+ "description": "Text to use within the back link component. If `html` is provided, the `text` option will be ignored. Defaults to 'Back'."
7
7
  },
8
8
  {
9
9
  "name": "html",
10
10
  "type": "string",
11
11
  "required": false,
12
- "description": "HTML to use within the back link component. If `html` is provided, the `text` argument will be ignored. Defaults to 'Back'."
12
+ "description": "HTML to use within the back link component. If `html` is provided, the `text` option will be ignored. Defaults to 'Back'."
13
13
  },
14
14
  {
15
15
  "name": "href",
@@ -128,8 +128,6 @@
128
128
  }
129
129
 
130
130
  .govuk-breadcrumbs__list {
131
- display: -webkit-box;
132
- display: -webkit-flex;
133
131
  display: -ms-flexbox;
134
132
  display: flex;
135
133
  }
@@ -9,13 +9,13 @@
9
9
  "name": "text",
10
10
  "type": "string",
11
11
  "required": true,
12
- "description": "If `html` is set, this is not required. Text to use within the breadcrumbs item. If `html` is provided, the `text` argument will be ignored."
12
+ "description": "If `html` is set, this is not required. Text to use within the breadcrumbs item. If `html` is provided, the `text` option will be ignored."
13
13
  },
14
14
  {
15
15
  "name": "html",
16
16
  "type": "string",
17
17
  "required": true,
18
- "description": "If `text` is set, this is not required. HTML to use within the breadcrumbs item. If `html` is provided, the `text` argument will be ignored."
18
+ "description": "If `text` is set, this is not required. HTML to use within the breadcrumbs item. If `html` is provided, the `text` option will be ignored."
19
19
  },
20
20
  {
21
21
  "name": "href",