@ministryofjustice/frontend 3.3.1 → 3.4.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.
- package/README.md +4 -10
- package/govuk-prototype-kit.config.json +5 -16
- package/moj/all.jquery.min.js +77 -3
- package/moj/all.js +2021 -1436
- package/moj/all.scss +2 -0
- package/moj/all.spec.js +15 -13
- package/moj/components/_all.scss +1 -0
- package/moj/components/action-bar/_action-bar.scss +4 -6
- package/moj/components/add-another/_add-another.scss +9 -7
- package/moj/components/add-another/add-another.js +90 -69
- package/moj/components/add-another/add-another.spec.js +165 -0
- package/moj/components/alert/README.md +0 -0
- package/moj/components/alert/_alert.scss +142 -0
- package/moj/components/alert/alert.js +247 -0
- package/moj/components/alert/alert.spec.helper.js +67 -0
- package/moj/components/alert/alert.spec.js +229 -0
- package/moj/components/alert/macro.njk +3 -0
- package/moj/components/alert/template.njk +83 -0
- package/moj/components/badge/_badge.scss +3 -4
- package/moj/components/banner/_banner.scss +5 -10
- package/moj/components/button-menu/_button-menu.scss +10 -9
- package/moj/components/button-menu/button-menu.js +139 -136
- package/moj/components/button-menu/button-menu.spec.js +295 -296
- package/moj/components/cookie-banner/_cookie-banner.scss +6 -5
- package/moj/components/currency-input/_currency-input.scss +4 -4
- package/moj/components/date-picker/README.md +14 -17
- package/moj/components/date-picker/_date-picker.scss +122 -106
- package/moj/components/date-picker/date-picker.js +473 -471
- package/moj/components/date-picker/date-picker.spec.js +971 -923
- package/moj/components/filter/README.md +1 -1
- package/moj/components/filter/_filter.scss +53 -75
- package/moj/components/filter-toggle-button/filter-toggle-button.js +71 -67
- package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +203 -205
- package/moj/components/form-validator/form-validator.js +117 -109
- package/moj/components/header/_header.scss +17 -19
- package/moj/components/identity-bar/_identity-bar.scss +5 -5
- package/moj/components/interruption-card/_interruption-card.scss +2 -2
- package/moj/components/messages/_messages.scss +12 -19
- package/moj/components/multi-file-upload/README.md +1 -1
- package/moj/components/multi-file-upload/_multi-file-upload.scss +34 -30
- package/moj/components/multi-file-upload/multi-file-upload.js +188 -152
- package/moj/components/multi-file-upload/multi-file-upload.spec.js +510 -0
- package/moj/components/multi-select/_multi-select.scss +4 -3
- package/moj/components/multi-select/multi-select.js +55 -50
- package/moj/components/multi-select/multi-select.spec.js +72 -79
- package/moj/components/notification-badge/_notification-badge.scss +12 -12
- package/moj/components/organisation-switcher/_organisation-switcher.scss +1 -1
- package/moj/components/page-header-actions/_page-header-actions.scss +3 -2
- package/moj/components/pagination/_pagination.scss +26 -31
- package/moj/components/password-reveal/_password-reveal.scss +1 -2
- package/moj/components/password-reveal/password-reveal.js +22 -21
- package/moj/components/password-reveal/password-reveal.spec.js +39 -37
- package/moj/components/primary-navigation/_primary-navigation.scss +26 -29
- package/moj/components/progress-bar/_progress-bar.scss +21 -26
- package/moj/components/rich-text-editor/_rich-text-editor.scss +17 -16
- package/moj/components/rich-text-editor/rich-text-editor.js +117 -103
- package/moj/components/search/_search.scss +6 -4
- package/moj/components/search-toggle/search-toggle.js +29 -30
- package/moj/components/search-toggle/search-toggle.scss +21 -15
- package/moj/components/search-toggle/search-toggle.spec.js +65 -70
- package/moj/components/side-navigation/_side-navigation.scss +12 -21
- package/moj/components/sortable-table/_sortable-table.scss +25 -23
- package/moj/components/sortable-table/sortable-table.js +139 -117
- package/moj/components/sortable-table/sortable-table.spec.js +362 -0
- package/moj/components/sub-navigation/_sub-navigation.scss +24 -28
- package/moj/components/tag/_tag.scss +8 -9
- package/moj/components/task-list/_task-list.scss +8 -7
- package/moj/components/ticket-panel/_ticket-panel.scss +14 -6
- package/moj/components/timeline/_timeline.scss +18 -20
- package/moj/filters/all.js +28 -30
- package/moj/filters/prototype-kit-13-filters.js +2 -1
- package/moj/helpers/_all.scss +1 -0
- package/moj/helpers/_hidden.scss +1 -1
- package/moj/helpers/_links.scss +20 -0
- package/moj/helpers.js +160 -31
- package/moj/helpers.spec.js +235 -0
- package/moj/init.js +2 -2
- package/moj/moj-frontend.min.css +2 -2
- package/moj/moj-frontend.min.js +77 -3
- package/moj/namespace.js +2 -1
- package/moj/objects/_filter-layout.scss +11 -10
- package/moj/objects/_scrollable-pane.scss +11 -14
- package/moj/settings/_colours.scss +5 -0
- package/moj/settings/_measurements.scss +0 -2
- package/moj/utilities/_hidden.scss +3 -3
- package/moj/utilities/_width-container.scss +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/* eslint-disable no-new */
|
|
2
|
+
|
|
3
|
+
const { queryByRole } = require('@testing-library/dom')
|
|
4
|
+
const { userEvent } = require('@testing-library/user-event')
|
|
5
|
+
|
|
6
|
+
require('./sortable-table.js')
|
|
7
|
+
|
|
8
|
+
const user = userEvent.setup()
|
|
9
|
+
|
|
10
|
+
const createComponent = (options = {}) => {
|
|
11
|
+
const html = `
|
|
12
|
+
<div>
|
|
13
|
+
<table class="govuk-table" data-module="moj-sortable-table">
|
|
14
|
+
<thead class="govuk-table__head">
|
|
15
|
+
<tr class="govuk-table__row">
|
|
16
|
+
<th scope="col" class="govuk-table__header" aria-sort="ascending">Name</th>
|
|
17
|
+
<th scope="col" class="govuk-table__header" aria-sort="none">Elevation</th>
|
|
18
|
+
<th scope="col" class="govuk-table__header" aria-sort="none">Continent</th>
|
|
19
|
+
<th scope="col" class="govuk-table__header govuk-table__header--numeric" aria-sort="none">First summit</th>
|
|
20
|
+
<th scope="col" class="govuk-table__header" aria-sort="none">Test nickname</th>
|
|
21
|
+
</tr>
|
|
22
|
+
</thead>
|
|
23
|
+
<tbody class="govuk-table__body">
|
|
24
|
+
<tr class="govuk-table__row">
|
|
25
|
+
<td class="govuk-table__cell">Aconcagua</td>
|
|
26
|
+
<td class="govuk-table__cell" data-sort-value="6961">6,961 meters</td>
|
|
27
|
+
<td class="govuk-table__cell">South America</td>
|
|
28
|
+
<td class="govuk-table__cell govuk-table__cell--numeric" data-sort-value="1897">1897</td>
|
|
29
|
+
<td class="govuk-table__cell"></td>
|
|
30
|
+
</tr>
|
|
31
|
+
<tr class="govuk-table__row">
|
|
32
|
+
<td class="govuk-table__cell">Everest</td>
|
|
33
|
+
<td class="govuk-table__cell" data-sort-value="8850">8,850 meters</td>
|
|
34
|
+
<td class="govuk-table__cell">Asia</td>
|
|
35
|
+
<td class="govuk-table__cell govuk-table__cell--numeric" data-sort-value="1953">1953</td>
|
|
36
|
+
<td class="govuk-table__cell">1Tallest</td>
|
|
37
|
+
</tr>
|
|
38
|
+
<tr class="govuk-table__row">
|
|
39
|
+
<td class="govuk-table__cell">Kilimanjaro</td>
|
|
40
|
+
<td class="govuk-table__cell" data-sort-value="5895">5,895 meters</td>
|
|
41
|
+
<td class="govuk-table__cell">Africa</td>
|
|
42
|
+
<td class="govuk-table__cell govuk-table__cell--numeric" data-sort-value="1889">1889</td>
|
|
43
|
+
<td class="govuk-table__cell">KiliJ89</td>
|
|
44
|
+
</tr>
|
|
45
|
+
<tr class="govuk-table__row">
|
|
46
|
+
<td class="govuk-table__cell">K2</td>
|
|
47
|
+
<td class="govuk-table__cell" data-sort-value="8611">8,611 meters</td>
|
|
48
|
+
<td class="govuk-table__cell">Asia</td>
|
|
49
|
+
<td class="govuk-table__cell govuk-table__cell--numeric" data-sort-value="1889">1954</td>
|
|
50
|
+
<td class="govuk-table__cell">1NearlyTallest</td>
|
|
51
|
+
</tr>
|
|
52
|
+
</tbody>
|
|
53
|
+
</table>
|
|
54
|
+
</div>`
|
|
55
|
+
|
|
56
|
+
document.body.insertAdjacentHTML('afterbegin', html)
|
|
57
|
+
const component = document.querySelector('[data-module="moj-sortable-table"]')
|
|
58
|
+
options.table = component
|
|
59
|
+
return { component, options }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
describe('sortable table', () => {
|
|
63
|
+
let component
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
;({ component } = createComponent())
|
|
67
|
+
new MOJFrontend.SortableTable({
|
|
68
|
+
table: component
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
afterEach(() => {
|
|
73
|
+
document.body.innerHTML = ''
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('initialises with buttons in headers', () => {
|
|
77
|
+
const headers = Array.from(component.querySelectorAll('th')).filter(
|
|
78
|
+
(header) => header.getAttribute('aria-sort')
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
for (const header of headers) {
|
|
82
|
+
const button = header.querySelector('button')
|
|
83
|
+
expect(button).toBeInTheDocument()
|
|
84
|
+
expect(button).toHaveTextContent(header.textContent)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('creates status box for announcements', () => {
|
|
89
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
90
|
+
expect(statusBox).toBeInTheDocument()
|
|
91
|
+
expect(statusBox).toHaveClass('govuk-visually-hidden')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('sorts ascending by Name on initial load', () => {
|
|
95
|
+
const tbody = component.querySelector('tbody')
|
|
96
|
+
const cells = tbody.querySelectorAll('tr td:first-child')
|
|
97
|
+
const values = Array.from(cells).map((cell) => cell.textContent.trim())
|
|
98
|
+
|
|
99
|
+
expect(component.querySelector('th')).toHaveAttribute(
|
|
100
|
+
'aria-sort',
|
|
101
|
+
'ascending'
|
|
102
|
+
)
|
|
103
|
+
expect(values).toEqual(['Aconcagua', 'Everest', 'K2', 'Kilimanjaro'])
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('sorts string column in descending order when clicked', async () => {
|
|
107
|
+
const nameHeaderButton = queryByRole(component, 'button', { name: 'Name' })
|
|
108
|
+
const tbody = component.querySelector('tbody')
|
|
109
|
+
|
|
110
|
+
await user.click(nameHeaderButton)
|
|
111
|
+
|
|
112
|
+
const descCells = tbody.querySelectorAll('tr td:first-child')
|
|
113
|
+
const descValues = Array.from(descCells).map((cell) =>
|
|
114
|
+
cell.textContent.trim()
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
expect(descValues).toEqual(['Kilimanjaro', 'K2', 'Everest', 'Aconcagua'])
|
|
118
|
+
expect(nameHeaderButton.parentElement).toHaveAttribute(
|
|
119
|
+
'aria-sort',
|
|
120
|
+
'descending'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
await user.click(nameHeaderButton)
|
|
124
|
+
|
|
125
|
+
const ascCells = tbody.querySelectorAll('tr td:first-child')
|
|
126
|
+
const ascValues = Array.from(ascCells).map((cell) =>
|
|
127
|
+
cell.textContent.trim()
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
expect(ascValues).toEqual(['Aconcagua', 'Everest', 'K2', 'Kilimanjaro'])
|
|
131
|
+
expect(nameHeaderButton.parentElement).toHaveAttribute(
|
|
132
|
+
'aria-sort',
|
|
133
|
+
'ascending'
|
|
134
|
+
)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('sorts numeric column using data-sort-value', async () => {
|
|
138
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
139
|
+
name: 'Elevation'
|
|
140
|
+
})
|
|
141
|
+
const tbody = component.querySelector('tbody')
|
|
142
|
+
|
|
143
|
+
await user.click(elevationHeaderButton)
|
|
144
|
+
|
|
145
|
+
const ascCells = tbody.querySelectorAll('tr td:nth-child(2)')
|
|
146
|
+
const ascValues = Array.from(ascCells).map((cell) =>
|
|
147
|
+
parseInt(cell.getAttribute('data-sort-value'))
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
expect(ascValues).toEqual([5895, 6961, 8611, 8850])
|
|
151
|
+
expect(elevationHeaderButton.parentElement).toHaveAttribute(
|
|
152
|
+
'aria-sort',
|
|
153
|
+
'ascending'
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
await user.click(elevationHeaderButton)
|
|
157
|
+
|
|
158
|
+
const descCells = tbody.querySelectorAll('tr td:nth-child(2)')
|
|
159
|
+
const descValues = Array.from(descCells).map((cell) =>
|
|
160
|
+
parseInt(cell.getAttribute('data-sort-value'))
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
expect(descValues).toEqual([8850, 8611, 6961, 5895])
|
|
164
|
+
expect(elevationHeaderButton.parentElement).toHaveAttribute(
|
|
165
|
+
'aria-sort',
|
|
166
|
+
'descending'
|
|
167
|
+
)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('sorts mixed data column without specified data-sort-value', async () => {
|
|
171
|
+
const nicknameHeaderButton = queryByRole(component, 'button', {
|
|
172
|
+
name: 'Test nickname'
|
|
173
|
+
})
|
|
174
|
+
const tbody = component.querySelector('tbody')
|
|
175
|
+
|
|
176
|
+
await user.click(nicknameHeaderButton)
|
|
177
|
+
|
|
178
|
+
const ascCells = tbody.querySelectorAll('tr td:nth-child(5)')
|
|
179
|
+
const ascValues = Array.from(ascCells).map((cell) =>
|
|
180
|
+
cell.textContent.trim()
|
|
181
|
+
)
|
|
182
|
+
// Values converted to numbers in getCellValue function for comparison
|
|
183
|
+
|
|
184
|
+
expect(ascValues).toEqual(['', '1NearlyTallest', '1Tallest', 'KiliJ89'])
|
|
185
|
+
expect(nicknameHeaderButton.parentElement).toHaveAttribute(
|
|
186
|
+
'aria-sort',
|
|
187
|
+
'ascending'
|
|
188
|
+
)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
test('updates status message when sorting', async () => {
|
|
192
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
193
|
+
name: 'Elevation'
|
|
194
|
+
})
|
|
195
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
196
|
+
|
|
197
|
+
await user.click(elevationHeaderButton)
|
|
198
|
+
|
|
199
|
+
expect(statusBox).toHaveTextContent('Sort by Elevation (ascending)')
|
|
200
|
+
|
|
201
|
+
await user.click(elevationHeaderButton)
|
|
202
|
+
|
|
203
|
+
expect(statusBox).toHaveTextContent('Sort by Elevation (descending)')
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
test('removes sort state from other columns when sorting a new column', async () => {
|
|
207
|
+
const nameHeaderButton = queryByRole(component, 'button', { name: 'Name' })
|
|
208
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
209
|
+
name: 'Elevation'
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
await user.click(elevationHeaderButton)
|
|
213
|
+
|
|
214
|
+
expect(nameHeaderButton.parentElement).toHaveAttribute('aria-sort', 'none')
|
|
215
|
+
expect(elevationHeaderButton.parentElement).toHaveAttribute(
|
|
216
|
+
'aria-sort',
|
|
217
|
+
'ascending'
|
|
218
|
+
)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('cycles through sort states: none -> ascending -> descending', async () => {
|
|
222
|
+
const headerButton = queryByRole(component, 'button', { name: 'Continent' })
|
|
223
|
+
const header = headerButton.parentElement
|
|
224
|
+
|
|
225
|
+
expect(header).toHaveAttribute('aria-sort', 'none')
|
|
226
|
+
|
|
227
|
+
await user.click(headerButton)
|
|
228
|
+
expect(header).toHaveAttribute('aria-sort', 'ascending')
|
|
229
|
+
|
|
230
|
+
await user.click(headerButton)
|
|
231
|
+
expect(header).toHaveAttribute('aria-sort', 'descending')
|
|
232
|
+
|
|
233
|
+
await user.click(headerButton)
|
|
234
|
+
expect(header).toHaveAttribute('aria-sort', 'ascending')
|
|
235
|
+
})
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
describe('sortable table options', () => {
|
|
239
|
+
let component
|
|
240
|
+
let options
|
|
241
|
+
|
|
242
|
+
beforeEach(() => {
|
|
243
|
+
;({ component, options } = createComponent())
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
afterEach(() => {
|
|
247
|
+
document.body.innerHTML = ''
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
test('uses default status message when no options provided', async () => {
|
|
251
|
+
new MOJFrontend.SortableTable(options)
|
|
252
|
+
|
|
253
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
254
|
+
name: 'Elevation'
|
|
255
|
+
})
|
|
256
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
257
|
+
|
|
258
|
+
await user.click(elevationHeaderButton)
|
|
259
|
+
expect(statusBox).toHaveTextContent('Sort by Elevation (ascending)')
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
test('uses custom status message when provided', async () => {
|
|
263
|
+
options.statusMessage = 'Sorted column: %heading% (order: %direction%)'
|
|
264
|
+
new MOJFrontend.SortableTable(options)
|
|
265
|
+
|
|
266
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
267
|
+
name: 'Elevation'
|
|
268
|
+
})
|
|
269
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
270
|
+
|
|
271
|
+
await user.click(elevationHeaderButton)
|
|
272
|
+
expect(statusBox).toHaveTextContent(
|
|
273
|
+
'Sorted column: Elevation (order: ascending)'
|
|
274
|
+
)
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test('uses custom ascending text when provided', async () => {
|
|
278
|
+
options.ascendingText = 'A to Z'
|
|
279
|
+
new MOJFrontend.SortableTable(options)
|
|
280
|
+
|
|
281
|
+
const nameHeaderButton = queryByRole(component, 'button', { name: 'Name' })
|
|
282
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
283
|
+
|
|
284
|
+
await user.click(nameHeaderButton)
|
|
285
|
+
await user.click(nameHeaderButton)
|
|
286
|
+
|
|
287
|
+
expect(statusBox).toHaveTextContent('Sort by Name (A to Z)')
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
test('uses custom descending text when provided', async () => {
|
|
291
|
+
options.descendingText = 'Z to A'
|
|
292
|
+
new MOJFrontend.SortableTable(options)
|
|
293
|
+
|
|
294
|
+
const nameHeaderButton = queryByRole(component, 'button', { name: 'Name' })
|
|
295
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
296
|
+
|
|
297
|
+
await user.click(nameHeaderButton)
|
|
298
|
+
|
|
299
|
+
expect(statusBox).toHaveTextContent('Sort by Name (Z to A)')
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
test('uses all custom options together', async () => {
|
|
303
|
+
options = {
|
|
304
|
+
table: component,
|
|
305
|
+
statusMessage: 'component sorted by %heading% in %direction% order',
|
|
306
|
+
ascendingText: 'lowest to highest',
|
|
307
|
+
descendingText: 'highest to lowest'
|
|
308
|
+
}
|
|
309
|
+
new MOJFrontend.SortableTable(options)
|
|
310
|
+
|
|
311
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
312
|
+
name: 'Elevation'
|
|
313
|
+
})
|
|
314
|
+
const statusBox = queryByRole(component.parentElement, 'status')
|
|
315
|
+
|
|
316
|
+
await user.click(elevationHeaderButton)
|
|
317
|
+
expect(statusBox).toHaveTextContent(
|
|
318
|
+
'component sorted by Elevation in lowest to highest order'
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
await user.click(elevationHeaderButton)
|
|
322
|
+
expect(statusBox).toHaveTextContent(
|
|
323
|
+
'component sorted by Elevation in highest to lowest order'
|
|
324
|
+
)
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
test('allows reinitialization of component without duplicating functionality', () => {
|
|
328
|
+
const { component, options } = createComponent()
|
|
329
|
+
new MOJFrontend.SortableTable(options)
|
|
330
|
+
new MOJFrontend.SortableTable(options) // Initialize again
|
|
331
|
+
|
|
332
|
+
// Check that we don't have duplicate buttons in headers
|
|
333
|
+
const headers = component.querySelectorAll('th[aria-sort]')
|
|
334
|
+
headers.forEach((header) => {
|
|
335
|
+
const buttons = header.querySelectorAll('button')
|
|
336
|
+
expect(buttons).toHaveLength(1)
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
test('maintains original sort when reinitialized', async () => {
|
|
341
|
+
const { component, options } = createComponent()
|
|
342
|
+
new MOJFrontend.SortableTable(options)
|
|
343
|
+
|
|
344
|
+
const elevationHeaderButton = queryByRole(component, 'button', {
|
|
345
|
+
name: 'Elevation'
|
|
346
|
+
})
|
|
347
|
+
await user.click(elevationHeaderButton)
|
|
348
|
+
|
|
349
|
+
new MOJFrontend.SortableTable(options) // Reinitialize
|
|
350
|
+
|
|
351
|
+
const cells = component.querySelectorAll('tbody tr td:nth-child(2)')
|
|
352
|
+
const values = Array.from(cells).map((cell) =>
|
|
353
|
+
parseInt(cell.getAttribute('data-sort-value'))
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
expect(values).toEqual([5895, 6961, 8611, 8850])
|
|
357
|
+
expect(elevationHeaderButton.parentElement).toHaveAttribute(
|
|
358
|
+
'aria-sort',
|
|
359
|
+
'ascending'
|
|
360
|
+
)
|
|
361
|
+
})
|
|
362
|
+
})
|
|
@@ -6,49 +6,45 @@
|
|
|
6
6
|
margin-bottom: govuk-spacing(7);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
.moj-sub-navigation__list {
|
|
11
|
-
font-size: 0; // Removes white space when using inline-block on child element.
|
|
12
|
-
list-style: none;
|
|
13
10
|
margin: 0;
|
|
14
11
|
padding: 0;
|
|
12
|
+
font-size: 0; // Removes white space when using inline-block on child element.
|
|
13
|
+
list-style: none;
|
|
15
14
|
|
|
16
15
|
@include govuk-media-query($from: tablet) {
|
|
17
|
-
box-shadow: inset 0 -1px 0 $govuk-border-colour;
|
|
18
16
|
width: 100%;
|
|
17
|
+
box-shadow: inset 0 -1px 0 $govuk-border-colour;
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
|
|
23
21
|
.moj-sub-navigation__item {
|
|
24
22
|
@include govuk-font(19);
|
|
25
|
-
box-shadow: inset 0 -1px 0 $govuk-border-colour;
|
|
26
23
|
display: block;
|
|
27
24
|
margin-top: -1px;
|
|
25
|
+
box-shadow: inset 0 -1px 0 $govuk-border-colour;
|
|
28
26
|
|
|
29
27
|
&:last-child {
|
|
30
28
|
box-shadow: none;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
@include govuk-media-query($from: tablet) {
|
|
34
|
-
box-shadow: none;
|
|
35
32
|
display: inline-block;
|
|
36
|
-
margin-right: govuk-spacing(4);
|
|
37
33
|
margin-top: 0;
|
|
34
|
+
margin-right: govuk-spacing(4);
|
|
35
|
+
box-shadow: none;
|
|
38
36
|
}
|
|
39
|
-
|
|
40
37
|
}
|
|
41
38
|
|
|
42
|
-
|
|
43
39
|
.moj-sub-navigation__link {
|
|
44
40
|
@include govuk-link-common;
|
|
45
41
|
@include govuk-link-style-default;
|
|
46
42
|
display: block;
|
|
43
|
+
position: relative;
|
|
47
44
|
padding-top: 12px;
|
|
48
45
|
padding-bottom: 12px;
|
|
49
46
|
padding-left: govuk-spacing(3);
|
|
50
47
|
text-decoration: none;
|
|
51
|
-
position: relative;
|
|
52
48
|
|
|
53
49
|
@include govuk-media-query($from: tablet) {
|
|
54
50
|
padding-left: 0;
|
|
@@ -64,54 +60,54 @@
|
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
&:focus {
|
|
67
|
-
color: govuk-colour("black"); // Focus colour on yellow should really be black.
|
|
68
63
|
position: relative; // Ensure focus sits above everything else.
|
|
64
|
+
color: govuk-colour("black"); // Focus colour on yellow should really be black.
|
|
69
65
|
box-shadow: none;
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
&:focus
|
|
73
|
-
background-color: govuk-colour("black");
|
|
68
|
+
&:focus::before {
|
|
74
69
|
content: "";
|
|
75
70
|
display: block;
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
position: absolute;
|
|
72
|
+
bottom: 0;
|
|
73
|
+
left: 0;
|
|
78
74
|
width: 5px;
|
|
75
|
+
height: 100%;
|
|
76
|
+
background-color: govuk-colour("black");
|
|
79
77
|
|
|
80
78
|
@include govuk-media-query($from: tablet) {
|
|
81
|
-
height: 5px;
|
|
82
79
|
width: 100%;
|
|
80
|
+
height: 5px;
|
|
83
81
|
}
|
|
84
82
|
}
|
|
85
|
-
|
|
86
83
|
}
|
|
87
84
|
|
|
88
|
-
|
|
89
85
|
.moj-sub-navigation__link[aria-current="page"] {
|
|
90
|
-
color: $govuk-link-active-colour;
|
|
91
86
|
position: relative;
|
|
87
|
+
color: $govuk-link-active-colour;
|
|
92
88
|
text-decoration: none;
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
background-color: $govuk-link-colour;
|
|
90
|
+
&::before {
|
|
96
91
|
content: "";
|
|
97
92
|
display: block;
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
position: absolute;
|
|
94
|
+
bottom: 0;
|
|
95
|
+
left: 0;
|
|
100
96
|
width: 5px;
|
|
97
|
+
height: 100%;
|
|
98
|
+
background-color: $govuk-link-colour;
|
|
101
99
|
|
|
102
100
|
@include govuk-media-query($from: tablet) {
|
|
103
|
-
height: 5px;
|
|
104
101
|
width: 100%;
|
|
102
|
+
height: 5px;
|
|
105
103
|
}
|
|
106
|
-
|
|
107
104
|
}
|
|
108
105
|
|
|
109
106
|
&:hover {
|
|
110
107
|
color: $govuk-link-hover-colour;
|
|
111
108
|
}
|
|
112
109
|
|
|
113
|
-
&:focus
|
|
110
|
+
&:focus::before {
|
|
114
111
|
background-color: govuk-colour("black");
|
|
115
112
|
}
|
|
116
|
-
|
|
117
113
|
}
|
|
@@ -4,52 +4,51 @@
|
|
|
4
4
|
|
|
5
5
|
.moj-tag {
|
|
6
6
|
border: 2px solid $govuk-brand-colour;
|
|
7
|
-
background-color: $govuk-brand-colour;
|
|
8
7
|
color: govuk-colour("white");
|
|
8
|
+
background-color: $govuk-brand-colour;
|
|
9
9
|
|
|
10
10
|
&--purple {
|
|
11
11
|
border: 2px solid govuk-colour("purple");
|
|
12
|
-
background-color: govuk-colour("purple");
|
|
13
12
|
color: govuk-colour("white");
|
|
13
|
+
background-color: govuk-colour("purple");
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
&--bright-purple {
|
|
17
17
|
border: 2px solid govuk-colour("bright-purple");
|
|
18
|
-
background-color: govuk-colour("bright-purple");
|
|
19
18
|
color: govuk-colour("white");
|
|
19
|
+
background-color: govuk-colour("bright-purple");
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
&--red,
|
|
23
23
|
&--error {
|
|
24
24
|
border: 2px solid govuk-colour("red");
|
|
25
|
-
background-color: govuk-colour("red");
|
|
26
25
|
color: govuk-colour("white");
|
|
26
|
+
background-color: govuk-colour("red");
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
&--green,
|
|
30
30
|
&--success {
|
|
31
31
|
border: 2px solid govuk-colour("green");
|
|
32
|
-
background-color: govuk-colour("green");
|
|
33
32
|
color: govuk-colour("white");
|
|
33
|
+
background-color: govuk-colour("green");
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
&--blue,
|
|
37
37
|
&--information {
|
|
38
38
|
border: 2px solid govuk-colour("blue");
|
|
39
|
-
background-color: govuk-colour("blue");
|
|
40
39
|
color: govuk-colour("white");
|
|
40
|
+
background-color: govuk-colour("blue");
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
&--black {
|
|
44
44
|
border: 2px solid govuk-colour("black");
|
|
45
|
-
background-color: govuk-colour("black");
|
|
46
45
|
color: govuk-colour("white");
|
|
46
|
+
background-color: govuk-colour("black");
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
&--grey {
|
|
50
50
|
border: 2px solid govuk-colour("dark-grey");
|
|
51
|
-
background-color: govuk-colour("dark-grey");
|
|
52
51
|
color: govuk-colour("white");
|
|
52
|
+
background-color: govuk-colour("dark-grey");
|
|
53
53
|
}
|
|
54
|
-
|
|
55
54
|
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
========================================================================== */
|
|
4
4
|
|
|
5
5
|
.moj-task-list {
|
|
6
|
-
list-style-type: none;
|
|
7
|
-
padding-left: 0;
|
|
8
6
|
margin-top: 0;
|
|
9
7
|
margin-bottom: 0;
|
|
8
|
+
padding-left: 0;
|
|
9
|
+
list-style-type: none;
|
|
10
10
|
@include govuk-media-query($from: tablet) {
|
|
11
11
|
min-width: 550px;
|
|
12
12
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
.moj-task-list__section {
|
|
16
16
|
display: table;
|
|
17
|
-
@include govuk-font($size:24, $weight: bold);
|
|
17
|
+
@include govuk-font($size: 24, $weight: bold);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
.moj-task-list__section-number {
|
|
@@ -29,18 +29,19 @@
|
|
|
29
29
|
.moj-task-list__items {
|
|
30
30
|
@include govuk-font($size: 19);
|
|
31
31
|
@include govuk-responsive-margin(9, "bottom");
|
|
32
|
-
list-style: none;
|
|
33
32
|
padding-left: 0;
|
|
33
|
+
list-style: none;
|
|
34
34
|
@include govuk-media-query($from: tablet) {
|
|
35
35
|
padding-left: govuk-spacing(6);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.moj-task-list__item {
|
|
40
|
-
|
|
40
|
+
// stylelint-disable-next-line declaration-no-important
|
|
41
41
|
margin-bottom: 0 !important;
|
|
42
42
|
padding-top: govuk-spacing(2);
|
|
43
43
|
padding-bottom: govuk-spacing(2);
|
|
44
|
+
border-bottom: 1px solid $govuk-border-colour;
|
|
44
45
|
@include govuk-clearfix;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -51,8 +52,8 @@
|
|
|
51
52
|
.moj-task-list__task-name {
|
|
52
53
|
display: block;
|
|
53
54
|
@include govuk-media-query($from: 450px) {
|
|
54
|
-
float: left;
|
|
55
55
|
width: 75%;
|
|
56
|
+
float: left;
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -61,8 +62,8 @@
|
|
|
61
62
|
margin-bottom: govuk-spacing(1);
|
|
62
63
|
|
|
63
64
|
@include govuk-media-query($from: 450px) {
|
|
64
|
-
float: right;
|
|
65
65
|
margin-top: 0;
|
|
66
66
|
margin-bottom: 0;
|
|
67
|
+
float: right;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
@include govuk-media-query($from: desktop) {
|
|
12
12
|
display: flex;
|
|
13
13
|
flex-wrap: nowrap;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
&--inline > * + * {
|
|
18
|
+
@include govuk-media-query($from: desktop) {
|
|
19
|
+
margin-left: govuk-spacing(3);
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -25,30 +27,36 @@
|
|
|
25
27
|
&__content {
|
|
26
28
|
display: block;
|
|
27
29
|
position: relative;
|
|
28
|
-
background-color: govuk-colour("light-grey");
|
|
29
|
-
padding: govuk-spacing(4);
|
|
30
30
|
margin-bottom: govuk-spacing(3);
|
|
31
|
-
|
|
31
|
+
padding: govuk-spacing(4);
|
|
32
32
|
border-left: 4px solid transparent;
|
|
33
|
+
background-color: govuk-colour("light-grey");
|
|
34
|
+
flex-grow: 1;
|
|
33
35
|
|
|
34
36
|
&--grey {
|
|
35
37
|
border-left-color: $govuk-border-colour;
|
|
36
38
|
}
|
|
39
|
+
|
|
37
40
|
&--blue {
|
|
38
41
|
border-left-color: govuk-colour("blue");
|
|
39
42
|
}
|
|
43
|
+
|
|
40
44
|
&--red {
|
|
41
45
|
border-left-color: govuk-colour("red");
|
|
42
46
|
}
|
|
47
|
+
|
|
43
48
|
&--yellow {
|
|
44
49
|
border-left-color: govuk-colour("yellow");
|
|
45
50
|
}
|
|
51
|
+
|
|
46
52
|
&--green {
|
|
47
53
|
border-left-color: govuk-colour("green");
|
|
48
54
|
}
|
|
55
|
+
|
|
49
56
|
&--purple {
|
|
50
57
|
border-left-color: govuk-colour("purple");
|
|
51
58
|
}
|
|
59
|
+
|
|
52
60
|
&--orange {
|
|
53
61
|
border-left-color: govuk-colour("orange");
|
|
54
62
|
}
|