govuk_publishing_components 63.0.0 → 63.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90f9e9423db2ea202bab6f85c3e7074c123d71a9905b1736355eca6b0487d0ef
4
- data.tar.gz: 512dc157f628a2e58004215a191f9ea2fadc95157e711107a8ab4e2d37da4fac
3
+ metadata.gz: 6d7be3bd8faf1d55b317bda8101dce15b87de9bc7ef96a090e8394d8f174442f
4
+ data.tar.gz: 77796278e71f2963c5898e84f587ea9ba08bf599ff24a9a7a785aeda2d3d5226
5
5
  SHA512:
6
- metadata.gz: afc7f05626ebca0e9ae1f224580c07feff4d0dd44fff9eb25afcd054665246cde4c98270ca73838767ffb6dcf5ba0ec36df04a1f976f36c4d7682e36012f9a53
7
- data.tar.gz: 814ab32a098c3f9709579f7c34604927f96668f3aeb615d4e4b0f512d041f3f58a2cea640085d6351e8f91748135de87bce7cac9e35157489d58e8f0a9bc5a30
6
+ metadata.gz: 61d1ad004cbfbcc2eee95cfc4a17930fcb7d38c7bb20b7cbec01861d0aaf35975af38e08d91216a339a1cee6efb0a628acc658439518eb5225c05acf1182907e
7
+ data.tar.gz: a2d709fbe8a6a84a7b0773db6f276d4a02595853039a6c0085a85c9536c048f47faf97ef7356ce7294e7f3e563b0f393505792b55c8dddcad59ac92580af535d
@@ -1,3 +1,4 @@
1
+ //= require sortablejs/Sortable.js
1
2
  window.GOVUK = window.GOVUK || {}
2
3
  window.GOVUK.Modules = window.GOVUK.Modules || {};
3
4
 
@@ -27,6 +28,9 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
27
28
  this.createAddAnotherButton()
28
29
  this.createRemoveButtons()
29
30
  this.removeEmptyFieldset()
31
+ if (this.module.dataset.sortable === 'true') {
32
+ this.makeSortable()
33
+ }
30
34
  this.updateFieldsetsAndButtons()
31
35
  }
32
36
 
@@ -102,12 +106,14 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
102
106
  visibleFields.forEach(function (field, index) {
103
107
  field.querySelector('legend').textContent = this.module.dataset.fieldsetLegend + ' ' + (index + 1)
104
108
 
105
- var trackedRemoveButton = field.parentNode.querySelector('.js-add-another__remove-button[data-ga4-event]')
109
+ var trackedButtons = field.parentNode.querySelectorAll(
110
+ '.js-add-another__remove-button[data-ga4-event], .gem-c-add-another__move-button[data-ga4-event]'
111
+ )
106
112
 
107
- if (trackedRemoveButton) {
108
- trackedRemoveButton.dataset.indexSection = this.startIndex + index
109
- trackedRemoveButton.dataset.indexSectionCount = this.indexSectionCount || visibleFields.length
110
- }
113
+ trackedButtons.forEach(function (button) {
114
+ button.dataset.indexSection = this.startIndex + index
115
+ button.dataset.indexSectionCount = this.indexSectionCount || visibleFields.length
116
+ }.bind(this))
111
117
  }.bind(this))
112
118
 
113
119
  if (this.module.dataset.emptyFields === 'false') {
@@ -117,6 +123,10 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
117
123
  )
118
124
  }
119
125
 
126
+ if (this.module.dataset.sortable === 'true') {
127
+ this.disableTopAndBottomButtons()
128
+ }
129
+
120
130
  var trackedAddAnotherButton = this.module.querySelector('.js-add-another__add-button[data-ga4-event]')
121
131
 
122
132
  if (trackedAddAnotherButton) {
@@ -125,15 +135,30 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
125
135
  }
126
136
  }
127
137
 
138
+ // Disable the top "Move up" and bottom "Move down" buttons when the list is sortable.
139
+ AddAnother.prototype.disableTopAndBottomButtons = function () {
140
+ this.module.querySelectorAll('.gem-c-add-another__move-button').forEach(function (button) {
141
+ button.removeAttribute('disabled')
142
+ })
143
+
144
+ var topMoveUpButton = this.module.querySelector('.js-add-another__fieldset:first-of-type .gem-c-add-another__move-button[data-action="move-up"]')
145
+ topMoveUpButton.setAttribute('disabled', true)
146
+
147
+ var bottomMoveDownButton = this.module.querySelector('.js-add-another__fieldset:last-of-type .gem-c-add-another__move-button[data-action="move-down"]')
148
+ bottomMoveDownButton.setAttribute('disabled', true)
149
+ }
150
+
128
151
  AddAnother.prototype.addNewFieldset = function (event) {
129
- var button = event.target
130
152
  var newFieldsetTemplate = this.module.querySelector('.js-add-another__empty-template')
131
153
  var newFieldset = newFieldsetTemplate.content.cloneNode(true).children[0]
132
154
  newFieldset.classList.add('js-add-another__fieldset')
133
155
  this.createRemoveButton(newFieldset, this.removeNewFieldset.bind(this))
134
- button.before(newFieldset)
156
+ newFieldsetTemplate.before(newFieldset)
135
157
 
136
- this.incrementAttributes(newFieldsetTemplate.content)
158
+ this.updateAttributes(newFieldsetTemplate.content)
159
+ if (this.module.dataset.sortable === 'true') {
160
+ this.makeSortable()
161
+ }
137
162
  this.updateFieldsetsAndButtons()
138
163
 
139
164
  // Initialise any modules included in new fieldset
@@ -160,7 +185,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
160
185
  }
161
186
 
162
187
  // Set attribute values for id, for and name of supplied fieldset
163
- AddAnother.prototype.incrementAttributes = function (fieldset) {
188
+ AddAnother.prototype.updateAttributes = function (fieldset, newIndex = null) {
164
189
  var matcher = /(.*[_[])([0-9]+)([_\]].*?)$/
165
190
  fieldset
166
191
  .querySelectorAll('label, input, select, textarea')
@@ -169,11 +194,117 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
169
194
  var value = element.getAttribute(attribute)
170
195
  var matched = matcher.exec(value)
171
196
  if (!matched) return
172
- var index = parseInt(matched[2], 10) + 1
197
+ var index = newIndex == null ? (parseInt(matched[2], 10) + 1) : newIndex
173
198
  element.setAttribute(attribute, matched[1] + index + matched[3])
174
199
  })
175
200
  })
176
201
  }
177
202
 
203
+ AddAnother.prototype.makeSortable = function () {
204
+ this.removeMoveButtons()
205
+ this.addMoveButtons()
206
+ this.hideOrderInputs()
207
+ this.sortableList = window.Sortable.create(this.module, {
208
+ dataIdAttr: 'data-sortable-id',
209
+ disabled: true
210
+ })
211
+ }
212
+
213
+ AddAnother.prototype.getOrderInputs = function () {
214
+ return this.module.querySelectorAll('.js-add-another__fieldset:not([hidden]) .js-add-another__order-input input')
215
+ }
216
+
217
+ AddAnother.prototype.hideOrderInputs = function () {
218
+ this.getOrderInputs().forEach(function (orderInput) {
219
+ orderInput.closest('.js-add-another__order-input').hidden = true
220
+ })
221
+ }
222
+
223
+ AddAnother.prototype.addMoveButtons = function () {
224
+ var visibleFields = this.module.querySelectorAll('.js-add-another__fieldset:not([hidden])')
225
+ visibleFields.forEach(function (field, index) {
226
+ field.dataset.sortableId = 'js-add-another__sortable-' + index + '-fieldset'
227
+ var wrapper = document.createElement('div')
228
+ wrapper.className = 'gem-c-add-another__move-button-wrapper'
229
+ this.addButton(wrapper, 'move-up')
230
+ this.addButton(wrapper, 'move-down')
231
+ field.prepend(wrapper)
232
+ }.bind(this))
233
+ }
234
+
235
+ AddAnother.prototype.addButton = function (wrapper, action) {
236
+ var button = document.createElement('button')
237
+ button.className = 'govuk-button gem-c-button--secondary-quiet gem-c-add-another__move-button'
238
+ button.innerText = action === 'move-up' ? 'Move up' : 'Move down'
239
+ button.dataset.action = action
240
+ if (!this.disableGa4) {
241
+ button.dataset.ga4Event = this.createEventData({ action: action })
242
+ }
243
+
244
+ button.addEventListener('click', this.moveFieldset.bind(this))
245
+ wrapper.prepend(button)
246
+ }
247
+
248
+ AddAnother.prototype.moveFieldset = function (event) {
249
+ event.preventDefault()
250
+
251
+ var button = event.currentTarget
252
+ var action = button.dataset.action
253
+ var fieldset = button.closest('.js-add-another__fieldset')
254
+
255
+ var sortableId = fieldset.dataset.sortableId
256
+
257
+ var order = this.sortableList.toArray()
258
+ var index = order.indexOf(sortableId)
259
+
260
+ // pull the item we're moving out of the order
261
+ order.splice(index, 1)
262
+
263
+ // put it back in at the correct position
264
+ if (action === 'move-down') {
265
+ order.splice(index + 1, 0, sortableId)
266
+ } else if (action === 'move-up') {
267
+ order.splice(index - 1, 0, sortableId)
268
+ }
269
+
270
+ this.sortableList.sort(order, true)
271
+ this.updateFieldsetsAndButtons()
272
+
273
+ var visibleFields = this.module.querySelectorAll('.js-add-another__fieldset:not([hidden])')
274
+ visibleFields.forEach(function (field, index) {
275
+ this.updateAttributes(field, index)
276
+ }.bind(this))
277
+
278
+ var triggeredByKeyboard = event.detail === 0
279
+ if (triggeredByKeyboard) {
280
+ this.preserveElementFocus(button, fieldset, action, visibleFields)
281
+ }
282
+
283
+ this.updateOrderInputs()
284
+ }
285
+
286
+ AddAnother.prototype.preserveElementFocus = function (button, fieldset, action, visibleFields) {
287
+ let target = button
288
+ if (action === 'move-up' && fieldset === visibleFields[0]) {
289
+ target = button.parentNode.querySelector('button[data-action="move-down"]')
290
+ } else if (action === 'move-down' && fieldset === visibleFields[visibleFields.length - 1]) {
291
+ target = button.parentNode.querySelector('button[data-action="move-up"]')
292
+ }
293
+ target.focus()
294
+ }
295
+
296
+ AddAnother.prototype.removeMoveButtons = function () {
297
+ var wrappers = this.module.querySelectorAll('.gem-c-add-another__move-button-wrapper')
298
+ wrappers.forEach((button) => {
299
+ button.remove()
300
+ })
301
+ }
302
+
303
+ AddAnother.prototype.updateOrderInputs = function () {
304
+ this.getOrderInputs().forEach(function (orderInput, index) {
305
+ orderInput.value = index + 1
306
+ })
307
+ }
308
+
178
309
  Modules.AddAnother = AddAnother
179
310
  })(window.GOVUK.Modules)
@@ -11,4 +11,22 @@
11
11
  .js-add-another__remove-button--hidden {
12
12
  display: none;
13
13
  }
14
+
15
+ .gem-c-fieldset {
16
+ position: relative;
17
+ }
18
+
19
+ .gem-c-add-another__move-button[disabled] {
20
+ display: none;
21
+ }
22
+
23
+ .gem-c-add-another__move-button-wrapper {
24
+ position: absolute;
25
+ top: 0;
26
+ right: 0;
27
+ }
28
+
29
+ .gem-c-add-another__move-button {
30
+ margin-left: govuk-spacing(2);
31
+ }
14
32
  }
@@ -1,46 +1,24 @@
1
1
  @import "govuk_publishing_components/individual_component_support";
2
2
 
3
+ $gap: govuk-spacing(1);
4
+
3
5
  .gem-c-figure {
4
- border-top: 1px solid $govuk-border-colour;
5
- padding-top: govuk-spacing(3);
6
6
  margin: 0;
7
- margin-bottom: govuk-spacing(8);
8
- @include govuk-clearfix;
9
-
10
- @include govuk-media-query($until: tablet) {
11
- margin-bottom: govuk-spacing(6);
12
- }
7
+ display: table;
13
8
  }
14
9
 
15
10
  .gem-c-figure__image {
16
- display: block;
17
- width: 100%;
18
-
19
- @include govuk-media-query($from: tablet) {
20
- float: inline-start;
21
- width: 50%;
22
- }
11
+ max-width: 100%;
12
+ display: table-row;
23
13
  }
24
14
 
25
15
  .gem-c-figure__figcaption {
26
- @include govuk-font(16);
27
-
28
- @include govuk-media-query($from: tablet) {
29
- display: block;
30
- vertical-align: top;
31
- box-sizing: border-box;
32
- float: inline-end;
33
- padding-inline-start: govuk-spacing(3);
34
- width: 50%;
35
- }
36
-
37
- @include govuk-media-query($until: tablet) {
38
- margin-top: govuk-spacing(2);
39
- }
16
+ display: table-caption;
17
+ caption-side: bottom;
40
18
  }
41
19
 
42
20
  .gem-c-figure__figcaption-text {
43
- margin: 0;
44
- margin-bottom: govuk-spacing(2);
45
- @include govuk-font(16);
21
+ margin: govuk-spacing(2) 0 0 0;
22
+ color: $govuk-secondary-text-colour;
23
+ @include govuk-font(19);
46
24
  }
@@ -3,7 +3,7 @@
3
3
 
4
4
  // stylelint-disable declaration-no-important
5
5
  @include govuk-media-query($media-type: print) {
6
- .govuk-pagination * {
6
+ .gem-c-pagination * {
7
7
  color: $govuk-print-text-colour !important;
8
8
  }
9
9
  }
@@ -13,21 +13,23 @@
13
13
  }
14
14
 
15
15
  figure {
16
- width: 100%;
17
- clear: both;
18
- overflow: hidden;
19
16
  margin: 0 0 govuk-spacing(4) 0;
17
+ display: table;
20
18
 
21
19
  img {
22
- display: inline;
23
- text-align: center;
24
- width: auto;
25
- height: auto;
26
20
  max-width: 100%;
21
+ display: table-row;
27
22
  }
28
23
 
29
24
  figcaption {
30
- @include govuk-font($size: 16);
25
+ display: table-caption;
26
+ caption-side: bottom;
27
+ }
28
+
29
+ figcaption p {
30
+ margin: govuk-spacing(2) 0 0 0;
31
+ color: $govuk-secondary-text-colour;
32
+ @include govuk-font(19);
31
33
  }
32
34
  }
33
35
  }
@@ -6,6 +6,7 @@
6
6
  add_button_text ||= "Add another"
7
7
  empty_fields ||= false
8
8
  disable_ga4 ||= nil
9
+ sortable ||= false
9
10
 
10
11
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
11
12
  component_helper.add_class("gem-c-add-another")
@@ -15,6 +16,7 @@
15
16
  fieldset_legend:,
16
17
  empty_fields:,
17
18
  disable_ga4:,
19
+ sortable:,
18
20
  })
19
21
  %>
20
22
 
@@ -26,6 +28,14 @@
26
28
  legend_text: "#{fieldset_legend} #{index + 1}",
27
29
  heading_size: "m",
28
30
  } do %>
31
+ <% if sortable %>
32
+ <div class="js-add-another__order-input">
33
+ <label class="gem-c-label govuk-label">
34
+ Position<span class='govuk-visually-hidden'> for <%= fieldset_legend %></span>
35
+ <%= item[:order_input] %>
36
+ </label>
37
+ </div>
38
+ <% end %>
29
39
  <div class="js-add-another__destroy-checkbox">
30
40
  <%= item[:destroy_checkbox] %>
31
41
  </div>
@@ -5,6 +5,8 @@
5
5
  breadcrumbs ||= []
6
6
  collapse_on_mobile ||= false
7
7
  inverse ||= false
8
+ local_assigns[:aria] ||= {}
9
+ local_assigns[:aria][:label] ||= "Breadcrumb"
8
10
 
9
11
  breadcrumb_presenter = GovukPublishingComponents::Presenters::Breadcrumbs.new(breadcrumbs)
10
12
 
@@ -15,7 +17,6 @@
15
17
 
16
18
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
17
19
  component_helper.add_class(classes.join(" "))
18
- component_helper.add_aria_attribute({ label: "Breadcrumb" })
19
20
  component_helper.add_data_attribute({ module: "ga4-link-tracker" })
20
21
  %>
21
22
 
@@ -5,6 +5,7 @@
5
5
  credit ||= ""
6
6
  src ||= nil
7
7
  local_assigns[:lang] ||= "en"
8
+ local_assigns[:margin_bottom] ||= 8
8
9
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
9
10
  component_helper.add_class("gem-c-figure")
10
11
  %>
@@ -5,7 +5,7 @@
5
5
  brand ||= false
6
6
 
7
7
  brand_helper = GovukPublishingComponents::AppHelpers::BrandHelper.new(brand)
8
- card_helper = GovukPublishingComponents::Presenters::ImageCardHelper.new(local_assigns, brand_helper)
8
+ card_helper = GovukPublishingComponents::Presenters::ImageCardHelper.new(local_assigns)
9
9
  shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
10
10
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
11
11
  component_helper.add_class("gem-c-image-card")
@@ -4,29 +4,10 @@
4
4
  items ||= nil
5
5
 
6
6
  component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
7
- component_helper.add_class("govuk-pagination")
7
+ component_helper.add_class("gem-c-pagination govuk-pagination")
8
8
  component_helper.add_class("govuk-pagination--block") if items.blank?
9
9
  component_helper.add_aria_attribute({ label: t("components.pagination.pagination") })
10
10
  component_helper.add_data_attribute({ module: "ga4-link-tracker" }) unless disable_ga4
11
- %>
12
- <% prev_icon = capture do %>
13
- <svg class="govuk-pagination__icon govuk-pagination__icon--prev" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
14
- <path d="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"></path>
15
- </svg>
16
- <% end %>
17
- <% next_icon = capture do %>
18
- <svg class="govuk-pagination__icon govuk-pagination__icon--next" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
19
- <path d="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"></path>
20
- </svg>
21
- <% end %>
22
- <%
23
- if local_assigns[:next_page].present?
24
- local_assigns[:next_page][:icon] = next_icon
25
- end
26
-
27
- if local_assigns[:previous_page].present?
28
- local_assigns[:previous_page][:icon] = prev_icon
29
- end
30
11
 
31
12
  pagination_helper = GovukPublishingComponents::Presenters::PaginationHelper.new(local_assigns)
32
13
 
@@ -121,3 +121,49 @@ examples:
121
121
  <option value="92bbe2da-8d5f-480b-8da1-50b18e317654">Accelerated Capability Environment</option>
122
122
  </select>
123
123
  <div class="govuk-form-group">
124
+ sortable:
125
+ description: |
126
+ Adding `sortable` to the component will allow users to rearrange the items in the list.
127
+
128
+ This component uses SortableJS. When JavaScript is disabled a set of inputs will be shown allowing users to
129
+ provide an order index for each item.
130
+
131
+ For this to work, each field must have an `order_index` input provided.
132
+ data:
133
+ fieldset_legend: "Person"
134
+ add_button_text: "Add another person"
135
+ sortable: true
136
+ items:
137
+ - fields: >
138
+ <div class="govuk-form-group">
139
+ <label for="sortable_person_0_name" class="gem-c-label govuk-label">Full name</label>
140
+ <input class="gem-c-input govuk-input" id="sortable_person_0_name" name="person[0]name" value="Person A">
141
+ </div>
142
+ destroy_checkbox: >
143
+ <div class="govuk-checkboxes" data-module="govuk-checkboxes">
144
+ <div class="govuk-checkboxes__item">
145
+ <input type="checkbox" name="person[0][_destroy]" id="sortable_person_0__destroy" class="govuk-checkboxes__input">
146
+ <label for="sortable_person_0__destroy" class="govuk-label govuk-checkboxes__label">Delete</label>
147
+ </div>
148
+ </div>
149
+ order_input: >
150
+ <input class="gem-c-input govuk-input govuk-input--width-2" id="sortable_person_0_order" name="person[0]order" value="1">
151
+ - fields: >
152
+ <div class="govuk-form-group">
153
+ <label for="sortable_person_1_name" class="gem-c-label govuk-label">Full name</label>
154
+ <input class="gem-c-input govuk-input" id="sortable_person_1_name" name="person[1]name" value="Person B">
155
+ </div>
156
+ destroy_checkbox: >
157
+ <div class="govuk-checkboxes" data-module="govuk-checkboxes">
158
+ <div class="govuk-checkboxes__item">
159
+ <input type="checkbox" name="person[1][_destroy]" id="sortable_person_1__destroy" class="govuk-checkboxes__input">
160
+ <label for="sortable_person_1__destroy" class="govuk-label govuk-checkboxes__label">Delete</label>
161
+ </div>
162
+ </div>
163
+ order_input: >
164
+ <input class="gem-c-input govuk-input govuk-input--width-2" id="sortable_person_1_order" name="person[1]order" value="2">
165
+ empty:
166
+ <div class="govuk-form-group">
167
+ <label for="sortable_person_2_name" class="gem-c-label govuk-label">Full name</label>
168
+ <input class="gem-c-input govuk-input" id="sortable_person_2_name" name="person[2]name">
169
+ </div>
@@ -1,5 +1,5 @@
1
1
  name: Figure
2
- description: A figure containing an image that never exceeds the component’s width
2
+ description: A figure containing an image and optional caption.
3
3
  body: |
4
4
  A figure should be used for images that are referenced within a page, but which can be moved around without affecting the flow of the page [(see guidance here)](https://developer.mozilla.org/en/docs/Web/HTML/Element/figure)
5
5
 
@@ -15,29 +15,30 @@ uses_component_wrapper_helper: true
15
15
  examples:
16
16
  default:
17
17
  data:
18
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg'
18
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg
19
19
  figure_with_alt_text:
20
20
  data:
21
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg'
22
- alt: 'An image of the lords chamber'
21
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg
22
+ alt: An image of the lords chamber
23
23
  figure_with_caption:
24
+ description: The image will fill the available space but not exceed the width of the container or its own width. The caption will always be the same width as the image.
24
25
  data:
25
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg'
26
- alt: 'An image of the lords chamber'
27
- caption: 'The Lords Chamber'
26
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg
27
+ alt: An image of the lords chamber
28
+ caption: The Lords Chamber on the 14th of August. A large number of people are in attendance, filling the seats in the lower and upper areas. Several people are wearing hats.
28
29
  right_to_left_with_caption:
29
30
  data:
30
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/image_data/file/31637/s300_Visas_-_Website.jpg'
31
- alt: 'تأشيرات'
32
- caption: 'تأشيرات'
31
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/image_data/file/31637/s300_Visas_-_Website.jpg
32
+ alt: تأشيرات
33
+ caption: تأشيرات
33
34
  context:
34
35
  right_to_left: true
35
36
  figure_with_credit:
36
37
  data:
37
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg'
38
- credit: Wallis Crankled
38
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg
39
+ credit: Roger Harris
39
40
  figure_with_caption_and_credit:
40
41
  data:
41
- src: 'https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg'
42
- caption: The Lords Chamber
43
- credit: Wallis Crankled
42
+ src: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/feature/image/54374/s630_the_lords_chamber.jpg
43
+ caption: The Lords Chamber on the 14th of August. A large number of people are in attendance, filling the seats in the lower and upper areas. Several people are wearing hats.
44
+ credit: Roger Harris
@@ -849,6 +849,7 @@ examples:
849
849
  <h5>This is a h5 title</h5>
850
850
  <h6>This is a h6 title</h6>
851
851
  image:
852
+ description: Govspeak images are styled to mimic the [figure component](/component-guide/figure).
852
853
  data:
853
854
  block: |
854
855
  <figure class="image embedded">
@@ -859,6 +860,7 @@ examples:
859
860
  <p>Deforested area. Credit: Blue Ventures-Garth Cripps</p>
860
861
  </figcaption>
861
862
  </figure>
863
+ <p>This is a regular paragraph of text to demonstrate the spacing between it and the image above.</p>
862
864
  lists:
863
865
  data:
864
866
  block: |
@@ -6,12 +6,11 @@ module GovukPublishingComponents
6
6
 
7
7
  attr_reader :href, :large, :extra_details, :extra_details_no_indent, :heading_text, :metadata, :lang, :image_loading, :image_src, :two_thirds, :large_font_size_mobile
8
8
 
9
- def initialize(local_assigns, brand_helper)
9
+ def initialize(local_assigns)
10
10
  @href = local_assigns[:href]
11
11
  @extra_details = local_assigns[:extra_details] || []
12
12
  @image_src = local_assigns[:image_src]
13
13
  @image_alt = local_assigns[:image_alt] || ""
14
- @image_loading = local_assigns[:image_loading] || "auto"
15
14
  @srcset = local_assigns[:srcset] || nil
16
15
  @sizes = local_assigns[:sizes] || nil
17
16
  @image_loading = local_assigns[:image_loading] || "auto"
@@ -24,8 +23,6 @@ module GovukPublishingComponents
24
23
  @extra_details_no_indent = local_assigns[:extra_details_no_indent]
25
24
  @metadata = local_assigns[:metadata]
26
25
  @lang = local_assigns[:lang]
27
-
28
- @brand_helper = brand_helper
29
26
  end
30
27
 
31
28
  def large_mobile_font_size?
@@ -36,18 +33,13 @@ module GovukPublishingComponents
36
33
  end
37
34
 
38
35
  def media
39
- image
40
- end
41
-
42
- def image
43
- classes = %w[gem-c-image-card__image-wrapper]
44
36
  height = 200
45
37
  width = 300
46
38
  height = 90 if @two_thirds
47
39
  width = 90 if @two_thirds
48
40
 
49
41
  if @image_src
50
- content_tag(:figure, class: classes) do
42
+ content_tag(:figure, class: "gem-c-image-card__image-wrapper") do
51
43
  image_tag(
52
44
  @image_src,
53
45
  class: "gem-c-image-card__image",
@@ -67,6 +59,7 @@ module GovukPublishingComponents
67
59
 
68
60
  content_tag(:p, class: "gem-c-image-card__context") do
69
61
  if @context[:date]
62
+ @context[:date] = Date.parse(@context[:date]) if @context[:date].is_a? String
70
63
  date = content_tag(:time, l(@context[:date], format: "%e %B %Y"), datetime: @context[:date].iso8601, lang: "en")
71
64
  dash = content_tag(:span, " — ", 'aria-hidden': true)
72
65
 
@@ -82,9 +75,11 @@ module GovukPublishingComponents
82
75
  end
83
76
 
84
77
  def description
85
- return content_tag(:div, @description, class: "gem-c-image-card__description gem-c-image-card__description--large-font-size-mobile") if @description && large_mobile_font_size?
78
+ return unless @description
86
79
 
87
- content_tag(:div, @description, class: "gem-c-image-card__description") if @description
80
+ classes = %w[gem-c-image-card__description]
81
+ classes << "gem-c-image-card__description--large-font-size-mobile" if large_mobile_font_size?
82
+ content_tag(:div, @description, class: classes)
88
83
  end
89
84
  end
90
85
  end
@@ -11,6 +11,7 @@ module GovukPublishingComponents
11
11
  next: local_assigns[:next_page] || nil,
12
12
  prev: local_assigns[:previous_page] || nil,
13
13
  }
14
+
14
15
  @items = local_assigns[:items] || nil
15
16
 
16
17
  @disable_ga4 = local_assigns[:disable_ga4] || nil
@@ -32,7 +33,7 @@ module GovukPublishingComponents
32
33
  end
33
34
 
34
35
  def has_links?
35
- has_pages? || @prev_link || @next_link
36
+ has_pages? || @prev_link.present? || @next_link.present?
36
37
  end
37
38
 
38
39
  def has_pages?
@@ -72,7 +73,7 @@ module GovukPublishingComponents
72
73
  def arrow_link_helper(direction:)
73
74
  arrow_link_options = @arrow_links[direction.to_sym]
74
75
 
75
- return if arrow_link_options.blank?
76
+ return if arrow_link_options.blank? || !valid_link?(arrow_link_options)
76
77
 
77
78
  { href: nil, label: nil, title: nil, icon: nil, **arrow_link_options.symbolize_keys } => { href:, label:, title:, icon: }
78
79
 
@@ -86,6 +87,11 @@ module GovukPublishingComponents
86
87
  next: "Next",
87
88
  }[direction.to_sym]
88
89
 
90
+ icon = {
91
+ prev: previous_icon,
92
+ next: next_icon,
93
+ }[direction.to_sym]
94
+
89
95
  ga4_link = ga4_link_event(text: label || title, section:)
90
96
 
91
97
  link_text_classes = %w[govuk-pagination__link-title]
@@ -101,6 +107,24 @@ module GovukPublishingComponents
101
107
  end
102
108
  end
103
109
  end
110
+
111
+ private
112
+
113
+ def previous_icon
114
+ '<svg class="govuk-pagination__icon govuk-pagination__icon--prev" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
115
+ <path d="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"></path>
116
+ </svg>'.squish.html_safe
117
+ end
118
+
119
+ def next_icon
120
+ '<svg class="govuk-pagination__icon govuk-pagination__icon--next" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
121
+ <path d="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"></path>
122
+ </svg>'.squish.html_safe
123
+ end
124
+
125
+ def valid_link?(link)
126
+ link.key?(:href)
127
+ end
104
128
  end
105
129
  end
106
130
  end
@@ -124,14 +124,26 @@ module GovukPublishingComponents
124
124
  end
125
125
 
126
126
  def related_world_locations
127
- content_item_links_for("world_locations").each do |link|
128
- build_world_locations_path_for link
127
+ links = Array(@content_item.dig("links", "world_locations"))
128
+
129
+ links.map do |link|
130
+ {
131
+ path: build_world_locations_path_for(link),
132
+ text: link["title"],
133
+ locale: link["locale"],
134
+ }
129
135
  end
130
136
  end
131
137
 
132
138
  def build_world_locations_path_for(link)
133
- slug = link[:text].parameterize
134
- link[:path] ||= "/world/#{slug}/news"
139
+ if link["document_type"] == "world_location_news"
140
+ link["base_path"]
141
+ elsif link["document_type"] == "world_location" && link.dig("links", "world_location_news").any?
142
+ link.dig("links", "world_location_news", 0, "base_path")
143
+ else
144
+ slug = link["title"].parameterize
145
+ "/world/#{slug}/news"
146
+ end
135
147
  end
136
148
 
137
149
  def related_statistical_data_sets
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "63.0.0".freeze
2
+ VERSION = "63.1.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 63.0.0
4
+ version: 63.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
@@ -2118,7 +2118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2118
2118
  - !ruby/object:Gem::Version
2119
2119
  version: '0'
2120
2120
  requirements: []
2121
- rubygems_version: 4.0.1
2121
+ rubygems_version: 4.0.2
2122
2122
  specification_version: 4
2123
2123
  summary: A gem to document components in GOV.UK frontend applications
2124
2124
  test_files: []