@ons/design-system 60.0.3 → 61.0.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/components/accordion/_macro.njk +2 -3
- package/components/accordion/_macro.spec.js +9 -9
- package/components/accordion/accordion.dom.js +4 -4
- package/components/accordion/accordion.js +14 -14
- package/components/accordion/accordion.spec.js +6 -6
- package/components/collapsible/_macro.njk +20 -28
- package/components/collapsible/_macro.spec.js +15 -15
- package/components/{collapsible/_collapsible.scss → details/_details.scss} +14 -14
- package/components/details/_macro.njk +30 -0
- package/components/details/_macro.spec.js +151 -0
- package/components/details/details.dom.js +13 -0
- package/components/details/details.js +66 -0
- package/components/details/details.spec.js +103 -0
- package/components/hero/_hero.scss +2 -2
- package/components/question/_macro.njk +4 -4
- package/components/question/_macro.spec.js +14 -14
- package/components/summary/_macro.njk +1 -1
- package/components/summary/_macro.spec.js +148 -1
- package/components/summary/_summary.scss +6 -2
- package/components/table/_macro.spec.js +10 -8
- package/components/video/_macro.njk +18 -4
- package/components/video/_macro.spec.js +46 -33
- package/components/video/_video.scss +4 -0
- package/components/video/video.dom.js +13 -0
- package/components/video/video.js +30 -0
- package/components/video/video.spec.js +72 -0
- package/css/main.css +3 -3
- package/css/print.css +1 -1
- package/js/main.js +2 -1
- package/package.json +2 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
- package/scss/main.scss +1 -1
- package/scss/objects/_page.scss +1 -1
- package/scss/objects/_spacing.scss +1 -1
- package/scss/overrides/hcm.scss +1 -1
- package/scss/print.scss +1 -1
- package/components/collapsible/collapsible.dom.js +0 -13
- package/components/collapsible/collapsible.js +0 -66
- package/components/collapsible/collapsible.spec.js +0 -103
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export default class Details {
|
|
2
|
+
constructor(detailsElement) {
|
|
3
|
+
this.saveState = detailsElement.getAttribute('data-save-state') === 'true';
|
|
4
|
+
this.open = detailsElement.getAttribute('data-open') === 'true';
|
|
5
|
+
this.group = detailsElement.getAttribute('data-group');
|
|
6
|
+
|
|
7
|
+
// Elements
|
|
8
|
+
this.details = detailsElement;
|
|
9
|
+
this.detailsHeader = this.details.querySelector('.ons-js-details-heading');
|
|
10
|
+
|
|
11
|
+
// Initialise
|
|
12
|
+
const detailsId = detailsElement.getAttribute('id');
|
|
13
|
+
|
|
14
|
+
if (localStorage.getItem(detailsId) || this.open) {
|
|
15
|
+
this.setOpen(true);
|
|
16
|
+
this.details['setAttribute']('open', '');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.detailsHeader.addEventListener('click', this.toggle.bind(this));
|
|
20
|
+
this.detailsHeader.addEventListener('keydown', this.keyboardInteraction.bind(this));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
toggle(event) {
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
this.setOpen(!this.isOpen);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setOpen(open) {
|
|
29
|
+
if (open !== this.isOpen) {
|
|
30
|
+
const action = open ? 'Open' : 'Close';
|
|
31
|
+
const openAttribute = open ? 'set' : 'remove';
|
|
32
|
+
|
|
33
|
+
this.isOpen = open;
|
|
34
|
+
this.details[`${openAttribute}Attribute`]('open', '');
|
|
35
|
+
this.detailsHeader.setAttribute('data-ga-action', `${action} panel`);
|
|
36
|
+
|
|
37
|
+
if (this.onOpen && this.onClose) {
|
|
38
|
+
if (open) {
|
|
39
|
+
this.onOpen();
|
|
40
|
+
} else {
|
|
41
|
+
this.onClose();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (this.saveState === true && open === true) {
|
|
47
|
+
localStorage.setItem(this.details.getAttribute('id'), true);
|
|
48
|
+
} else {
|
|
49
|
+
localStorage.removeItem(this.details.getAttribute('id'));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
keyboardInteraction(event) {
|
|
54
|
+
const keyCode = event.which;
|
|
55
|
+
switch (keyCode) {
|
|
56
|
+
// Enter/Space
|
|
57
|
+
case 13:
|
|
58
|
+
case 32:
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
event.stopPropagation();
|
|
61
|
+
|
|
62
|
+
this.toggle(event);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
|
+
|
|
3
|
+
const EXAMPLE_DETAILS_BASIC = {
|
|
4
|
+
id: 'details-id',
|
|
5
|
+
title: 'Title for details',
|
|
6
|
+
content: 'Content for details',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
describe('script: details', () => {
|
|
10
|
+
it('begins open when specified', async () => {
|
|
11
|
+
await setTestPage(
|
|
12
|
+
'/test',
|
|
13
|
+
renderComponent('details', {
|
|
14
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
15
|
+
open: true,
|
|
16
|
+
}),
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const openAttribute = await page.$eval('.ons-js-details', node => node.open !== null);
|
|
20
|
+
expect(openAttribute).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('when the details heading is clicked to open the details', () => {
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
await setTestPage('/test', renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
26
|
+
await page.click('.ons-js-details-heading');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('sets the `open` attribute', async () => {
|
|
30
|
+
const openAttribute = await page.$eval('.ons-js-details', node => node.open !== null);
|
|
31
|
+
expect(openAttribute).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('sets the `ga` attributes', async () => {
|
|
35
|
+
const gaHeadingAttribute = await page.$eval('.ons-js-details-heading', element => element.getAttribute('data-ga-action'));
|
|
36
|
+
|
|
37
|
+
expect(gaHeadingAttribute).toBe('Open panel');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('when the details heading is focused', () => {
|
|
42
|
+
beforeEach(async () => {
|
|
43
|
+
await setTestPage('/test', renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
44
|
+
await page.focus('.ons-js-details-heading');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('when the space bar is pressed', () => {
|
|
48
|
+
beforeEach(async () => {
|
|
49
|
+
await page.keyboard.press('Space');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('opens the details content', async () => {
|
|
53
|
+
const openAttribute = await page.$eval('.ons-js-details', node => node.open !== null);
|
|
54
|
+
expect(openAttribute).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('when the Enter key is pressed', () => {
|
|
59
|
+
beforeEach(async () => {
|
|
60
|
+
await page.keyboard.press('Enter');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('opens the details content', async () => {
|
|
64
|
+
const openAttribute = await page.$eval('.ons-js-details', node => node.open !== null);
|
|
65
|
+
expect(openAttribute).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('when the state is set to save', () => {
|
|
71
|
+
beforeEach(async () => {
|
|
72
|
+
await setTestPage(
|
|
73
|
+
'/test',
|
|
74
|
+
renderComponent('details', {
|
|
75
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
76
|
+
saveState: true,
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('when the details is opened', () => {
|
|
82
|
+
beforeEach(async () => {
|
|
83
|
+
await page.click('.ons-js-details-heading');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('sets state in localStorage', async () => {
|
|
87
|
+
const localStorage = await page.evaluate(() => localStorage.getItem('details-id'));
|
|
88
|
+
expect(localStorage).toBe('true');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('when the details is closed', () => {
|
|
93
|
+
beforeEach(async () => {
|
|
94
|
+
await page.click('.ons-js-details-heading');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('removes state in localStorage', async () => {
|
|
98
|
+
const localStorage = await page.evaluate(() => localStorage.getItem('details-id'));
|
|
99
|
+
expect(localStorage).toBe(null);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
min-height: 300px;
|
|
17
17
|
position: relative;
|
|
18
18
|
|
|
19
|
-
&--has-
|
|
19
|
+
&--has-details {
|
|
20
20
|
align-items: flex-start; // Prevents undesired shift if not enough content
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
text-decoration-thickness: 2px;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
.ons-
|
|
62
|
+
.ons-details__heading {
|
|
63
63
|
color: inherit;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
{% if params.definition %}
|
|
20
20
|
{% set questionDefinition %}
|
|
21
|
-
{% from "components/
|
|
22
|
-
{% call
|
|
21
|
+
{% from "components/details/_macro.njk" import onsDetails %}
|
|
22
|
+
{% call onsDetails({
|
|
23
23
|
"id": params.definition.id,
|
|
24
24
|
"classes": 'ons-u-mb-m',
|
|
25
25
|
"title": params.definition.title
|
|
@@ -109,8 +109,8 @@
|
|
|
109
109
|
{% endif %}
|
|
110
110
|
|
|
111
111
|
{% if params.justification %}
|
|
112
|
-
{% from "components/
|
|
113
|
-
{% call
|
|
112
|
+
{% from "components/details/_macro.njk" import onsDetails %}
|
|
113
|
+
{% call onsDetails({
|
|
114
114
|
"id": params.justification.id,
|
|
115
115
|
"classes": 'ons-u-mb-m',
|
|
116
116
|
"title": params.justification.title | default('Why we ask this question')
|
|
@@ -163,21 +163,21 @@ describe('macro: question', () => {
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
describe('mode: with definition', () => {
|
|
166
|
-
it('outputs the expected
|
|
166
|
+
it('outputs the expected details', () => {
|
|
167
167
|
const faker = templateFaker();
|
|
168
|
-
const
|
|
168
|
+
const detailsSpy = faker.spy('details');
|
|
169
169
|
|
|
170
170
|
faker.renderComponent('question', EXAMPLE_QUESTION_DEFINITION);
|
|
171
171
|
|
|
172
|
-
expect(
|
|
173
|
-
expect(
|
|
174
|
-
expect(
|
|
172
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('classes', 'ons-u-mb-m');
|
|
173
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('id', 'definition-id');
|
|
174
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('title', 'Definition title');
|
|
175
175
|
});
|
|
176
176
|
|
|
177
|
-
it('outputs the expected
|
|
177
|
+
it('outputs the expected details call content', () => {
|
|
178
178
|
const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_DEFINITION));
|
|
179
179
|
|
|
180
|
-
expect($('.ons-
|
|
180
|
+
expect($('.ons-details__content > p').text()).toBe('Definition content');
|
|
181
181
|
});
|
|
182
182
|
});
|
|
183
183
|
|
|
@@ -227,21 +227,21 @@ describe('macro: question', () => {
|
|
|
227
227
|
});
|
|
228
228
|
|
|
229
229
|
describe('mode: with justification', () => {
|
|
230
|
-
it('outputs the expected
|
|
230
|
+
it('outputs the expected details', () => {
|
|
231
231
|
const faker = templateFaker();
|
|
232
|
-
const
|
|
232
|
+
const detailsSpy = faker.spy('details');
|
|
233
233
|
|
|
234
234
|
faker.renderComponent('question', EXAMPLE_QUESTION_JUSTIFICATION);
|
|
235
235
|
|
|
236
|
-
expect(
|
|
237
|
-
expect(
|
|
238
|
-
expect(
|
|
236
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('classes', 'ons-u-mb-m');
|
|
237
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('id', 'justification-id');
|
|
238
|
+
expect(detailsSpy.occurrences[0]).toHaveProperty('title', 'Justification title');
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
-
it('outputs the expected
|
|
241
|
+
it('outputs the expected details call content', () => {
|
|
242
242
|
const $ = cheerio.load(renderComponent('question', EXAMPLE_QUESTION_JUSTIFICATION));
|
|
243
243
|
|
|
244
|
-
expect($('.ons-
|
|
244
|
+
expect($('.ons-details__content > p').text()).toBe('Justification content');
|
|
245
245
|
});
|
|
246
246
|
});
|
|
247
247
|
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
{% endif %}
|
|
113
113
|
|
|
114
114
|
{% if group.summaryLink %}
|
|
115
|
-
<div class="ons-summary__link{% if group.placeholderText or group.rows %} ons-u-pt-s{% endif %}{% if group.placeholderText is not defined and group.rows | length > 1 %} ons-u-bt{% endif %}">
|
|
115
|
+
<div class="ons-summary__link{% if group.placeholderText or group.rows %} ons-u-pt-s{% endif %}{% if group.placeholderText is not defined and group.rows | length > 1 %} ons-u-bt{% endif %}{% if not group.last %} ons-u-mb-xl{% endif %}">
|
|
116
116
|
<a {% if group.summaryLink.attributes %}{% for attribute, value in (group.summaryLink.attributes.items() if group.summaryLink.attributes is mapping and group.summaryLink.attributes.items else group.summaryLink.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %} href="{{ group.summaryLink.url }}">{{ group.summaryLink.text }}</a>
|
|
117
117
|
</div>
|
|
118
118
|
{% endif %}
|
|
@@ -115,7 +115,6 @@ const EXAMPLE_SUMMARY_GROUPS = {
|
|
|
115
115
|
{
|
|
116
116
|
id: 'group-id-1',
|
|
117
117
|
groupTitle: 'group title',
|
|
118
|
-
headers: ['Header 1', 'Header 2', 'Header 3'],
|
|
119
118
|
...EXAMPLE_SUMMARY_ROWS,
|
|
120
119
|
},
|
|
121
120
|
],
|
|
@@ -136,6 +135,123 @@ const EXAMPLE_SUMMARY_GROUPS_NO_ROWS = {
|
|
|
136
135
|
],
|
|
137
136
|
};
|
|
138
137
|
|
|
138
|
+
const EXAMPLE_SUMMARY_HOUSEHOLD_GROUP = {
|
|
139
|
+
rows: [
|
|
140
|
+
{
|
|
141
|
+
rowItems: [
|
|
142
|
+
{
|
|
143
|
+
rowTitle: 'row item 1',
|
|
144
|
+
valueList: [
|
|
145
|
+
{
|
|
146
|
+
text: 'list item 1',
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
actions: [
|
|
150
|
+
{
|
|
151
|
+
text: 'Change',
|
|
152
|
+
ariaLabel: 'Change list item',
|
|
153
|
+
url: '#0',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
text: 'Remove',
|
|
157
|
+
ariaLabel: 'Remove list item',
|
|
158
|
+
url: '#0',
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
rowTitle: 'row item 2',
|
|
164
|
+
valueList: [
|
|
165
|
+
{
|
|
166
|
+
text: 'list item 2',
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
actions: [
|
|
170
|
+
{
|
|
171
|
+
text: 'Change',
|
|
172
|
+
ariaLabel: 'Remove list item',
|
|
173
|
+
url: '#0',
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
rowTitle: 'row item 3',
|
|
179
|
+
valueList: [
|
|
180
|
+
{
|
|
181
|
+
text: 'list item 3',
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
actions: [
|
|
185
|
+
{
|
|
186
|
+
text: 'Change',
|
|
187
|
+
ariaLabel: 'Change list item',
|
|
188
|
+
url: '#0',
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
rowItems: [
|
|
196
|
+
{
|
|
197
|
+
rowTitle: 'row item 4',
|
|
198
|
+
valueList: [
|
|
199
|
+
{
|
|
200
|
+
text: 'list item 4',
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
actions: [
|
|
204
|
+
{
|
|
205
|
+
text: 'Change',
|
|
206
|
+
ariaLabel: 'Change answer',
|
|
207
|
+
url: '#0',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
text: 'Remove',
|
|
211
|
+
ariaLabel: 'Change list item',
|
|
212
|
+
url: '#0',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
rowTitle: 'row item 5',
|
|
218
|
+
valueList: [
|
|
219
|
+
{
|
|
220
|
+
text: 'list item 5',
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
actions: [
|
|
224
|
+
{
|
|
225
|
+
text: 'Change',
|
|
226
|
+
ariaLabel: 'Change list item',
|
|
227
|
+
url: '#0',
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
rowTitle: 'row item 6',
|
|
233
|
+
valueList: [
|
|
234
|
+
{
|
|
235
|
+
text: 'list item 6',
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
actions: [
|
|
239
|
+
{
|
|
240
|
+
text: 'Change',
|
|
241
|
+
ariaLabel: 'Change list item',
|
|
242
|
+
url: '#0',
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
summaryLink: {
|
|
250
|
+
text: 'Summary link',
|
|
251
|
+
url: '#0',
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
|
|
139
255
|
const EXAMPLE_SUMMARY_BASIC = {
|
|
140
256
|
summaries: [
|
|
141
257
|
{
|
|
@@ -162,6 +278,31 @@ const EXAMPLE_SUMMARY_WITH_NO_ROWS = {
|
|
|
162
278
|
],
|
|
163
279
|
};
|
|
164
280
|
|
|
281
|
+
const EXAMPLE_SUMMARY_MULTIPLE_GROUPS = {
|
|
282
|
+
summaries: [
|
|
283
|
+
{
|
|
284
|
+
summaryTitle: 'summary title',
|
|
285
|
+
groups: [
|
|
286
|
+
{
|
|
287
|
+
id: 'group-id-1',
|
|
288
|
+
groupTitle: 'group title',
|
|
289
|
+
...EXAMPLE_SUMMARY_ROWS,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: 'group-id-2',
|
|
293
|
+
groupTitle: 'group title',
|
|
294
|
+
...EXAMPLE_SUMMARY_HOUSEHOLD_GROUP,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: 'group-id-3',
|
|
298
|
+
groupTitle: 'group title',
|
|
299
|
+
...EXAMPLE_SUMMARY_ROWS,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
};
|
|
305
|
+
|
|
165
306
|
describe('macro: summary', () => {
|
|
166
307
|
describe('mode: general', () => {
|
|
167
308
|
it('passes jest-axe checks', async () => {
|
|
@@ -200,6 +341,12 @@ describe('macro: summary', () => {
|
|
|
200
341
|
|
|
201
342
|
expect($('.ons-summary__group-title').text()).toBe('group title');
|
|
202
343
|
});
|
|
344
|
+
|
|
345
|
+
it('has larger margin between groups if the top one is a household style summary', () => {
|
|
346
|
+
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_MULTIPLE_GROUPS));
|
|
347
|
+
|
|
348
|
+
expect($('.ons-summary__group:nth-last-of-type(2) .ons-summary__link').hasClass('ons-u-mb-xl')).toBe(true);
|
|
349
|
+
});
|
|
203
350
|
});
|
|
204
351
|
|
|
205
352
|
describe('part: row', () => {
|
|
@@ -178,7 +178,7 @@ $hub-row-spacing: 1.3rem;
|
|
|
178
178
|
&__item-title,
|
|
179
179
|
&__values,
|
|
180
180
|
&__actions {
|
|
181
|
-
flex:
|
|
181
|
+
flex: 4;
|
|
182
182
|
padding-top: $summary-row-spacing;
|
|
183
183
|
vertical-align: top;
|
|
184
184
|
|
|
@@ -192,9 +192,13 @@ $hub-row-spacing: 1.3rem;
|
|
|
192
192
|
justify-content: right;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
&__button {
|
|
196
|
+
align-self: flex-start;
|
|
197
|
+
}
|
|
198
|
+
|
|
195
199
|
&__item-title,
|
|
196
200
|
&__values {
|
|
197
|
-
flex:
|
|
201
|
+
flex: 7.3;
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
&__item-title--2 {
|
|
@@ -356,14 +356,16 @@ describe('macro: table', () => {
|
|
|
356
356
|
|
|
357
357
|
faker.renderComponent('table', params);
|
|
358
358
|
|
|
359
|
-
expect(buttonSpy.occurrences).toEqual([
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
359
|
+
expect(buttonSpy.occurrences).toEqual([
|
|
360
|
+
{
|
|
361
|
+
text: 'Submit form',
|
|
362
|
+
id: 'submit-form-button',
|
|
363
|
+
classes: 'custom-button-class',
|
|
364
|
+
url: 'https://example.com/link',
|
|
365
|
+
value: '42', // `| safe` filter is used in macro which makes a string
|
|
366
|
+
name: 'submit-form-button-name',
|
|
367
|
+
},
|
|
368
|
+
]);
|
|
367
369
|
});
|
|
368
370
|
});
|
|
369
371
|
});
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
{% from "components/external-link/_macro.njk" import onsExternalLink %}
|
|
1
2
|
{%- macro onsVideo(params) -%}
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
{% endif %}
|
|
3
|
+
|
|
4
|
+
{% set linkContents %}
|
|
5
|
+
{% if params.image.smallSrc %}
|
|
6
|
+
<img class="ons-video__img ons-u-mb-xs" {% if params.image.largeSrc %} srcset="{{ params.image.smallSrc }} 1x, {{ params.image.largeSrc }} 2x"{% endif %} src="{{ params.image.smallSrc }}" alt="{{ params.image.alt }}" loading="lazy">
|
|
7
|
+
{% endif %}
|
|
8
|
+
<span class="ons-video__link-text ons-u-mt-xs">{{ params.linkText }}</span>
|
|
9
|
+
{% endset %}
|
|
10
|
+
|
|
11
|
+
<div class="ons-video ons-js-video">
|
|
12
|
+
{{
|
|
13
|
+
onsExternalLink({
|
|
14
|
+
"url": params.videoLinkURL,
|
|
15
|
+
"classes": "ons-video__link ons-js-video-placeholder ons-u-db",
|
|
16
|
+
"linkText": linkContents
|
|
17
|
+
})
|
|
18
|
+
}}
|
|
19
|
+
<iframe data-src="{{ params.videoEmbedUrl }}" title="{{ params.title }}" class="ons-video__iframe ons-js-video-iframe ons-u-d-no" src="about:blank" frameborder="0" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
|
6
20
|
</div>
|
|
7
21
|
{%- endmacro -%}
|
|
@@ -7,54 +7,67 @@ import { renderComponent } from '../../tests/helpers/rendering';
|
|
|
7
7
|
|
|
8
8
|
const EXAMPLE_VIDEO_YOUTUBE = {
|
|
9
9
|
videoEmbedUrl: 'https://www.youtube.com/embed/_EGJlvkgbPo',
|
|
10
|
+
videoLinkURL: 'https://www.youtube.com/watch?v=_EGJlvkgbPo',
|
|
10
11
|
title: 'Census 2021 promotional TV advert',
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
linkText: 'Example link text',
|
|
13
|
+
image: {
|
|
14
|
+
smallSrc: 'example-small.png',
|
|
15
|
+
largeSrc: 'example-large.png',
|
|
16
|
+
alt: 'Example alt text',
|
|
17
|
+
},
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
describe('macro: video', () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
it('passes jest-axe checks', async () => {
|
|
22
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
23
|
+
|
|
24
|
+
const results = await axe($.html());
|
|
25
|
+
expect(results).toHaveNoViolations();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('outputs an `img` element with the expected `srcset`', () => {
|
|
29
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
30
|
+
|
|
31
|
+
expect($('.ons-video__img').attr('srcset')).toBe('example-small.png 1x, example-large.png 2x');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('outputs an `img` element with the expected `src`', () => {
|
|
35
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
22
36
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
37
|
+
expect($('.ons-video__img').attr('src')).toBe('example-small.png');
|
|
38
|
+
});
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
it('outputs an `img` element with the expected alt text', () => {
|
|
41
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
expect($('.ons-video__img').attr('alt')).toBe('Example alt text');
|
|
44
|
+
});
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
it('outputs the provided link text', () => {
|
|
47
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
expect(
|
|
50
|
+
$('.ons-video__link-text')
|
|
51
|
+
.text()
|
|
52
|
+
.trim(),
|
|
53
|
+
).toBe('Example link text');
|
|
38
54
|
});
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_VIMEO));
|
|
56
|
+
it('outputs a hyperlink with the provided `url`', () => {
|
|
57
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
43
58
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
59
|
+
expect($('.ons-video__link').attr('href')).toBe('https://www.youtube.com/watch?v=_EGJlvkgbPo');
|
|
60
|
+
});
|
|
47
61
|
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
it('outputs an <iframe> element with the provided `title`', () => {
|
|
63
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
expect($('iframe').attr('title')).toBe('Census 2021 promotional TV advert');
|
|
66
|
+
});
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
it('outputs an <iframe> element with the provided `videoEmbedUrl` data attribute', () => {
|
|
69
|
+
const $ = cheerio.load(renderComponent('video', EXAMPLE_VIDEO_YOUTUBE));
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
});
|
|
71
|
+
expect($('iframe').attr('data-src')).toBe('https://www.youtube.com/embed/_EGJlvkgbPo');
|
|
59
72
|
});
|
|
60
73
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import domready from '../../js/domready';
|
|
2
|
+
|
|
3
|
+
async function video() {
|
|
4
|
+
const videos = [...document.querySelectorAll('.ons-js-video')];
|
|
5
|
+
|
|
6
|
+
if (videos.length) {
|
|
7
|
+
const Video = (await import('./video')).default;
|
|
8
|
+
|
|
9
|
+
videos.forEach(component => new Video(component));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
domready(video);
|