@ons/design-system 66.0.2 → 67.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.spec.js +2 -8
- package/components/accordion/accordion.dom.js +2 -2
- package/components/accordion/accordion.spec.js +22 -19
- package/components/accordion/example-accordion-open.njk +3 -3
- package/components/card/_card.scss +1 -1
- package/components/checkboxes/_macro.njk +1 -1
- package/components/checkboxes/example-checkboxes-with-revealed-checkboxes-expanded.njk +1 -1
- package/components/checkboxes/example-checkboxes-with-revealed-checkboxes.njk +1 -1
- package/components/cookies-banner/_macro.njk +1 -1
- package/components/cookies-banner/_macro.spec.js +1 -1
- package/components/details/_details.scss +66 -57
- package/components/details/_macro.njk +4 -4
- package/components/details/_macro.spec.js +3 -10
- package/components/details/details.dom.js +1 -1
- package/components/details/details.js +13 -1
- package/components/details/details.spec.js +43 -11
- package/components/details/example-details-with-warning.njk +1 -2
- package/components/footer/_macro.njk +1 -1
- package/components/header/_macro.spec.js +128 -5
- package/components/header/example-header-external-with-navigation-and-search.njk +57 -0
- package/components/label/_macro.njk +2 -2
- package/components/navigation/_macro.njk +3 -1
- package/components/related-content/_macro.njk +28 -30
- package/components/section-navigation/_macro.njk +56 -55
- package/components/video/_macro.njk +11 -11
- package/css/main.css +1 -1
- package/css/print.css +1 -1
- package/layout/_template.njk +29 -30
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
- package/scss/objects/_page.scss +3 -5
- package/scss/print.scss +28 -5
- package/components/collapsible/_macro.njk +0 -22
- package/components/collapsible/_macro.spec.js +0 -151
|
@@ -57,10 +57,7 @@ describe('macro: accordion', () => {
|
|
|
57
57
|
it('has provided title text', () => {
|
|
58
58
|
const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
|
|
59
59
|
|
|
60
|
-
const titleText = $('.ons-details__title')
|
|
61
|
-
.first()
|
|
62
|
-
.text()
|
|
63
|
-
.trim();
|
|
60
|
+
const titleText = $('.ons-details__title').first().text().trim();
|
|
64
61
|
expect(titleText).toBe('Title for item 1');
|
|
65
62
|
});
|
|
66
63
|
|
|
@@ -84,10 +81,7 @@ describe('macro: accordion', () => {
|
|
|
84
81
|
it('has provided content text', () => {
|
|
85
82
|
const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
|
|
86
83
|
|
|
87
|
-
const titleText = $('.ons-details__content')
|
|
88
|
-
.first()
|
|
89
|
-
.text()
|
|
90
|
-
.trim();
|
|
84
|
+
const titleText = $('.ons-details__content').first().text().trim();
|
|
91
85
|
expect(titleText).toBe('Content for item 1');
|
|
92
86
|
});
|
|
93
87
|
|
|
@@ -8,9 +8,9 @@ async function initialiseAccordions() {
|
|
|
8
8
|
|
|
9
9
|
const Details = (await import('../details/details')).default;
|
|
10
10
|
const Accordion = (await import('./accordion')).default;
|
|
11
|
-
const detailsEls = detailsComponents.map(element => new Details(element));
|
|
11
|
+
const detailsEls = detailsComponents.map((element) => new Details(element));
|
|
12
12
|
|
|
13
|
-
toggleAllButtons.forEach(button => {
|
|
13
|
+
toggleAllButtons.forEach((button) => {
|
|
14
14
|
new Accordion(button, detailsEls);
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -39,10 +39,11 @@ describe('script: accordion', () => {
|
|
|
39
39
|
}),
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const detailsElementStates = await page.$$eval('.ons-js-details', (nodes) =>
|
|
43
|
+
nodes.map((node) => node.classList.contains('ons-details--open')),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(detailsElementStates).toEqual([true, true, true]);
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
it('sets toggle all button label to "Hide all" when open is specified', async () => {
|
|
@@ -54,7 +55,7 @@ describe('script: accordion', () => {
|
|
|
54
55
|
}),
|
|
55
56
|
);
|
|
56
57
|
|
|
57
|
-
const buttonText = await page.$eval('button[data-test-trigger]', element => element.innerText);
|
|
58
|
+
const buttonText = await page.$eval('button[data-test-trigger]', (element) => element.innerText);
|
|
58
59
|
expect(buttonText.trim()).toBe('Close all');
|
|
59
60
|
});
|
|
60
61
|
|
|
@@ -67,7 +68,7 @@ describe('script: accordion', () => {
|
|
|
67
68
|
}),
|
|
68
69
|
);
|
|
69
70
|
|
|
70
|
-
const ariaExpanded = await page.$eval('button[data-test-trigger]', element => element.getAttribute('aria-expanded'));
|
|
71
|
+
const ariaExpanded = await page.$eval('button[data-test-trigger]', (element) => element.getAttribute('aria-expanded'));
|
|
71
72
|
expect(ariaExpanded).toBe('true');
|
|
72
73
|
});
|
|
73
74
|
|
|
@@ -76,10 +77,11 @@ describe('script: accordion', () => {
|
|
|
76
77
|
|
|
77
78
|
await page.click('button[data-test-trigger]');
|
|
78
79
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
const detailsElementStates = await page.$$eval('.ons-js-details', (nodes) =>
|
|
81
|
+
nodes.map((node) => node.classList.contains('ons-details--open')),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(detailsElementStates).toEqual([true, true, true]);
|
|
83
85
|
});
|
|
84
86
|
|
|
85
87
|
it('closes all items when accordion `allbutton` is clicked twice', async () => {
|
|
@@ -88,23 +90,24 @@ describe('script: accordion', () => {
|
|
|
88
90
|
await page.click('button[data-test-trigger]');
|
|
89
91
|
await page.click('button[data-test-trigger]');
|
|
90
92
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
const detailsElementStates = await page.$$eval('.ons-js-details', (nodes) =>
|
|
94
|
+
nodes.map((node) => node.classList.contains('ons-details--open')),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(detailsElementStates).toEqual([false, false, false]);
|
|
95
98
|
});
|
|
96
99
|
|
|
97
100
|
it('starts with the toggle all button labelled as "Open all"', async () => {
|
|
98
101
|
await setTestPage('/test', renderComponent('accordion', EXAMPLE_ACCORDION_WITH_ALL_BUTTON));
|
|
99
102
|
|
|
100
|
-
const buttonText = await page.$eval('button[data-test-trigger]', element => element.innerText);
|
|
103
|
+
const buttonText = await page.$eval('button[data-test-trigger]', (element) => element.innerText);
|
|
101
104
|
expect(buttonText.trim()).toBe('Open all');
|
|
102
105
|
});
|
|
103
106
|
|
|
104
107
|
it('starts with the toggle all button aria-expanded set to false', async () => {
|
|
105
108
|
await setTestPage('/test', renderComponent('accordion', EXAMPLE_ACCORDION_WITH_ALL_BUTTON));
|
|
106
109
|
|
|
107
|
-
const ariaExpanded = await page.$eval('button[data-test-trigger]', element => element.getAttribute('aria-expanded'));
|
|
110
|
+
const ariaExpanded = await page.$eval('button[data-test-trigger]', (element) => element.getAttribute('aria-expanded'));
|
|
108
111
|
expect(ariaExpanded).toBe('false');
|
|
109
112
|
});
|
|
110
113
|
|
|
@@ -113,7 +116,7 @@ describe('script: accordion', () => {
|
|
|
113
116
|
|
|
114
117
|
await page.click('button[data-test-trigger]');
|
|
115
118
|
|
|
116
|
-
const buttonText = await page.$eval('button[data-test-trigger]', element => element.innerText);
|
|
119
|
+
const buttonText = await page.$eval('button[data-test-trigger]', (element) => element.innerText);
|
|
117
120
|
expect(buttonText.trim()).toBe('Close all');
|
|
118
121
|
});
|
|
119
122
|
|
|
@@ -122,7 +125,7 @@ describe('script: accordion', () => {
|
|
|
122
125
|
|
|
123
126
|
await page.click('button[data-test-trigger]');
|
|
124
127
|
|
|
125
|
-
const ariaExpanded = await page.$eval('button[data-test-trigger]', element => element.getAttribute('aria-expanded'));
|
|
128
|
+
const ariaExpanded = await page.$eval('button[data-test-trigger]', (element) => element.getAttribute('aria-expanded'));
|
|
126
129
|
expect(ariaExpanded).toBe('true');
|
|
127
130
|
});
|
|
128
131
|
|
|
@@ -133,7 +136,7 @@ describe('script: accordion', () => {
|
|
|
133
136
|
await page.click('#example-accordion-2 .ons-details__heading');
|
|
134
137
|
await page.click('#example-accordion-3 .ons-details__heading');
|
|
135
138
|
|
|
136
|
-
const buttonText = await page.$eval('button[data-test-trigger]', element => element.innerText);
|
|
139
|
+
const buttonText = await page.$eval('button[data-test-trigger]', (element) => element.innerText);
|
|
137
140
|
expect(buttonText.trim()).toBe('Close all');
|
|
138
141
|
});
|
|
139
142
|
});
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"text": "Areas (0)"
|
|
63
63
|
},
|
|
64
64
|
"value": "areas"
|
|
65
|
-
}
|
|
65
|
+
}
|
|
66
66
|
]
|
|
67
67
|
})
|
|
68
68
|
}}
|
|
@@ -98,14 +98,14 @@
|
|
|
98
98
|
"text": "Disability (67)"
|
|
99
99
|
},
|
|
100
100
|
"value": "disability"
|
|
101
|
-
}
|
|
101
|
+
}
|
|
102
102
|
]
|
|
103
103
|
})
|
|
104
104
|
}}
|
|
105
105
|
{% endset %}
|
|
106
106
|
|
|
107
107
|
<div class="ons-grid">
|
|
108
|
-
<div class="ons-grid__col ons-col-
|
|
108
|
+
<div class="ons-grid__col ons-col-4@m">
|
|
109
109
|
{{
|
|
110
110
|
onsAccordion({
|
|
111
111
|
"id": "accordion",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
{% set fields %}
|
|
8
8
|
{% if params.checkboxesLabel is defined %}
|
|
9
9
|
<p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
|
|
10
|
-
{% endif %}
|
|
10
|
+
{% endif %}
|
|
11
11
|
{% set hasOther = false %}
|
|
12
12
|
{% for checkbox in params.checkboxes %}
|
|
13
13
|
{% if checkbox.other %}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
{% set acceptedText = 'You have accepted all additional cookies.' %}
|
|
29
29
|
{% set rejectedText = 'You have rejected all additional cookies.' %}
|
|
30
30
|
{% set confirmationButtonText = 'Hide' %}
|
|
31
|
-
{% set contextSuffix = '
|
|
31
|
+
{% set contextSuffix = 'cookie message' %}
|
|
32
32
|
{% set beforeLinkPreferencesURL = 'You can' %}
|
|
33
33
|
{% set afterLinkPreferencesURL = 'change your cookie preferences</a> at any time.' %}
|
|
34
34
|
{% set beforeLinkStatementText = '<p>Cookies are small files stored on your device when you visit a website. We use some essential cookies to make this website work.</p><p>We would like to set' %}
|
|
@@ -215,7 +215,7 @@ describe('macro: cookies-banner', () => {
|
|
|
215
215
|
|
|
216
216
|
faker.renderComponent('cookies-banner', {});
|
|
217
217
|
|
|
218
|
-
expect(buttonSpy.occurrences[2].buttonContext).toBe('
|
|
218
|
+
expect(buttonSpy.occurrences[2].buttonContext).toBe('cookie message');
|
|
219
219
|
});
|
|
220
220
|
|
|
221
221
|
it('has `container--wide` class when `wide` is true', () => {
|
|
@@ -1,75 +1,81 @@
|
|
|
1
1
|
$details-caret-width: 1.5rem;
|
|
2
2
|
|
|
3
3
|
.ons-details {
|
|
4
|
-
&
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
&:focus {
|
|
19
|
-
.ons-details__title {
|
|
20
|
-
@extend %a-focus;
|
|
21
|
-
// extend details focus background behind caret
|
|
22
|
-
margin-left: -$details-caret-width;
|
|
23
|
-
padding-left: $details-caret-width;
|
|
24
|
-
}
|
|
25
|
-
.ons-details__icon .ons-icon {
|
|
26
|
-
fill: var(--ons-color-text-link-focus);
|
|
4
|
+
&--initialised & {
|
|
5
|
+
&__heading {
|
|
6
|
+
color: var(--ons-color-text-link);
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
display: inline-block;
|
|
9
|
+
outline: none;
|
|
10
|
+
padding: 0 0 0 $details-caret-width;
|
|
11
|
+
pointer-events: initial;
|
|
12
|
+
position: relative;
|
|
13
|
+
|
|
14
|
+
&::marker,
|
|
15
|
+
&::-webkit-details-marker {
|
|
16
|
+
display: none;
|
|
27
17
|
}
|
|
28
|
-
}
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
&:focus {
|
|
20
|
+
.ons-details__title {
|
|
21
|
+
@extend %a-focus;
|
|
22
|
+
// extend details focus background behind caret
|
|
23
|
+
margin-left: -$details-caret-width;
|
|
24
|
+
padding-left: $details-caret-width;
|
|
25
|
+
}
|
|
26
|
+
.ons-details__icon .ons-icon {
|
|
27
|
+
fill: var(--ons-color-text-link-focus);
|
|
28
|
+
}
|
|
34
29
|
}
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
|
|
31
|
+
&:hover:not(:focus) {
|
|
32
|
+
color: var(--ons-color-text-link-hover);
|
|
33
|
+
.ons-details__icon {
|
|
34
|
+
fill: var(--ons-color-text-link-hover);
|
|
35
|
+
}
|
|
36
|
+
.ons-details__title {
|
|
37
|
+
text-decoration: underline solid var(--ons-color-text-link-hover) 2px;
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
|
-
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
&__icon {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
fill: var(--ons-color-text-link);
|
|
45
|
+
height: $details-caret-width;
|
|
46
|
+
left: -0.15rem;
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: -0.2rem;
|
|
49
|
+
width: $details-caret-width;
|
|
50
|
+
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
font-weight: $font-weight-bold;
|
|
55
|
-
margin-bottom: 0;
|
|
56
|
-
text-underline-position: under;
|
|
57
|
-
transform: translateY(-1px);
|
|
58
|
-
}
|
|
52
|
+
&__content {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
&__title {
|
|
57
|
+
display: inline-block;
|
|
58
|
+
font-size: 1rem;
|
|
59
|
+
font-weight: $font-weight-bold;
|
|
60
|
+
margin-bottom: 0;
|
|
61
|
+
text-underline-position: under;
|
|
62
|
+
transform: translateY(-1px);
|
|
63
|
+
}
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
&--open & {
|
|
68
67
|
&__icon {
|
|
69
68
|
left: -0.1rem;
|
|
70
69
|
top: 0.2rem;
|
|
71
70
|
transform: rotate(90deg);
|
|
72
71
|
}
|
|
72
|
+
|
|
73
|
+
&__content {
|
|
74
|
+
border-left: 4px solid var(--ons-color-borders-indent);
|
|
75
|
+
display: block;
|
|
76
|
+
margin: 1rem 0 0;
|
|
77
|
+
padding: 0 0 0 1.3em;
|
|
78
|
+
}
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
&--accordion & {
|
|
@@ -110,12 +116,15 @@ $details-caret-width: 1.5rem;
|
|
|
110
116
|
padding: 0;
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
|
-
}
|
|
114
119
|
|
|
115
|
-
.ons-details--
|
|
116
|
-
&[open] {
|
|
120
|
+
&--accordion.ons-details--open {
|
|
117
121
|
.ons-details__icon {
|
|
122
|
+
position: absolute;
|
|
118
123
|
top: 1.2rem;
|
|
119
124
|
}
|
|
120
125
|
}
|
|
126
|
+
|
|
127
|
+
&__icon {
|
|
128
|
+
display: none;
|
|
129
|
+
}
|
|
121
130
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% macro onsDetails(params) %}
|
|
2
|
-
<
|
|
2
|
+
<div
|
|
3
3
|
id="{{ params.id }}"
|
|
4
4
|
class="ons-details ons-js-details{% if params.isAccordion %} ons-details--accordion{% endif %}{% if params.classes %} {{ params.classes }}{% endif %}"
|
|
5
5
|
{% if params.group %} data-group="{{ params.group }}"{% endif %}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
{% if params.saveState %} data-save-state="true"{% endif %}
|
|
8
8
|
{% if params.open %} data-open="true"{% endif %}
|
|
9
9
|
>
|
|
10
|
-
<
|
|
10
|
+
<div
|
|
11
11
|
class="ons-details__heading ons-js-details-heading"
|
|
12
12
|
{% if params.headingAttributes %}{% for attribute, value in (params.headingAttributes.items() if params.headingAttributes is mapping and params.headingAttributes.items else params.headingAttributes) %}{{ attribute }}{% if value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
|
|
13
13
|
>
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"iconType": "chevron"
|
|
21
21
|
})
|
|
22
22
|
}}</span>
|
|
23
|
-
</
|
|
23
|
+
</div>
|
|
24
24
|
<div id="{{ params.id }}-content" class="ons-details__content ons-js-details-content"
|
|
25
25
|
{% if params.contentAttributes %}{% for attribute, value in (params.contentAttributes.items() if params.contentAttributes is mapping and params.contentAttributes.items else params.contentAttributes) %}{{ attribute }}{% if value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
|
|
26
26
|
>
|
|
27
27
|
{{ params.content | safe }}{{ caller() if caller }}
|
|
28
28
|
</div>
|
|
29
|
-
</
|
|
29
|
+
</div>
|
|
30
30
|
{% endmacro %}
|
|
@@ -40,10 +40,7 @@ describe('macro: details', () => {
|
|
|
40
40
|
it('has provided title text', () => {
|
|
41
41
|
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
42
42
|
|
|
43
|
-
const titleText = $('.ons-details__title')
|
|
44
|
-
.first()
|
|
45
|
-
.text()
|
|
46
|
-
.trim();
|
|
43
|
+
const titleText = $('.ons-details__title').first().text().trim();
|
|
47
44
|
expect(titleText).toBe('Title for details');
|
|
48
45
|
});
|
|
49
46
|
|
|
@@ -62,9 +59,7 @@ describe('macro: details', () => {
|
|
|
62
59
|
it('has provided content text', () => {
|
|
63
60
|
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
64
61
|
|
|
65
|
-
const titleText = $('.ons-details__content')
|
|
66
|
-
.text()
|
|
67
|
-
.trim();
|
|
62
|
+
const titleText = $('.ons-details__content').text().trim();
|
|
68
63
|
expect(titleText).toEqual(expect.stringContaining('Content for details'));
|
|
69
64
|
});
|
|
70
65
|
|
|
@@ -143,9 +138,7 @@ describe('macro: details', () => {
|
|
|
143
138
|
it('calls with content', () => {
|
|
144
139
|
const $ = cheerio.load(renderComponent('details', { EXAMPLE_DETAILS_BASIC }, 'Example content...'));
|
|
145
140
|
|
|
146
|
-
const content = $('.ons-details__content')
|
|
147
|
-
.text()
|
|
148
|
-
.trim();
|
|
141
|
+
const content = $('.ons-details__content').text().trim();
|
|
149
142
|
expect(content).toEqual(expect.stringContaining('Example content...'));
|
|
150
143
|
});
|
|
151
144
|
});
|
|
@@ -6,7 +6,7 @@ async function initialiseDetailsEls() {
|
|
|
6
6
|
|
|
7
7
|
if (detailsComponents.length && !accordionComponents.length) {
|
|
8
8
|
const Details = (await import('./details')).default;
|
|
9
|
-
detailsComponents.map(element => new Details(element));
|
|
9
|
+
detailsComponents.map((element) => new Details(element));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -7,17 +7,25 @@ export default class Details {
|
|
|
7
7
|
// Elements
|
|
8
8
|
this.details = detailsElement;
|
|
9
9
|
this.detailsHeader = this.details.querySelector('.ons-js-details-heading');
|
|
10
|
+
this.content = this.details.querySelector('.ons-js-details-content');
|
|
10
11
|
|
|
11
12
|
// Initialise
|
|
12
13
|
const detailsId = detailsElement.getAttribute('id');
|
|
13
14
|
|
|
15
|
+
this.details.setAttribute('role', 'group');
|
|
16
|
+
this.detailsHeader.setAttribute('role', 'link');
|
|
17
|
+
this.detailsHeader.setAttribute('aria-controls', detailsId);
|
|
18
|
+
this.detailsHeader.setAttribute('tabindex', 0);
|
|
19
|
+
|
|
14
20
|
if (localStorage.getItem(detailsId) || this.open) {
|
|
15
21
|
this.setOpen(true);
|
|
16
|
-
|
|
22
|
+
} else {
|
|
23
|
+
this.setOpen(false);
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
this.detailsHeader.addEventListener('click', this.toggle.bind(this));
|
|
20
27
|
this.detailsHeader.addEventListener('keydown', this.keyboardInteraction.bind(this));
|
|
28
|
+
this.details.classList.add('ons-details--initialised');
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
toggle(event) {
|
|
@@ -28,10 +36,14 @@ export default class Details {
|
|
|
28
36
|
setOpen(open) {
|
|
29
37
|
if (open !== this.isOpen) {
|
|
30
38
|
const action = open ? 'Open' : 'Close';
|
|
39
|
+
const cls = open ? 'add' : 'remove';
|
|
31
40
|
const openAttribute = open ? 'set' : 'remove';
|
|
32
41
|
|
|
33
42
|
this.isOpen = open;
|
|
34
43
|
this.details[`${openAttribute}Attribute`]('open', '');
|
|
44
|
+
this.details.classList[cls]('ons-details--open');
|
|
45
|
+
this.detailsHeader.setAttribute('aria-expanded', open);
|
|
46
|
+
this.content.setAttribute('aria-hidden', !open);
|
|
35
47
|
this.detailsHeader.setAttribute('data-ga-action', `${action} panel`);
|
|
36
48
|
|
|
37
49
|
if (this.onOpen && this.onClose) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
1
|
+
import { renderComponent, renderTemplate, setTestPage } from '../../tests/helpers/rendering';
|
|
2
2
|
|
|
3
3
|
const EXAMPLE_DETAILS_BASIC = {
|
|
4
4
|
id: 'details-id',
|
|
@@ -6,6 +6,22 @@ const EXAMPLE_DETAILS_BASIC = {
|
|
|
6
6
|
content: 'Content for details',
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
const EXAMPLE_PAGE = `
|
|
10
|
+
${renderComponent('details', {
|
|
11
|
+
id: 'details-id',
|
|
12
|
+
title: 'Title for details',
|
|
13
|
+
content: 'Content for details',
|
|
14
|
+
})}
|
|
15
|
+
|
|
16
|
+
${renderComponent('details', {
|
|
17
|
+
id: 'details-id-2',
|
|
18
|
+
title: 'Title for details',
|
|
19
|
+
content: 'Content for details',
|
|
20
|
+
})}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const RENDERED_EXAMPLE_PAGE = renderTemplate(EXAMPLE_PAGE);
|
|
24
|
+
|
|
9
25
|
describe('script: details', () => {
|
|
10
26
|
it('begins open when specified', async () => {
|
|
11
27
|
await setTestPage(
|
|
@@ -16,8 +32,8 @@ describe('script: details', () => {
|
|
|
16
32
|
}),
|
|
17
33
|
);
|
|
18
34
|
|
|
19
|
-
const
|
|
20
|
-
expect(
|
|
35
|
+
const detailsOpenClass = await page.$eval('.ons-js-details', (node) => node.classList.contains('ons-details--open'));
|
|
36
|
+
expect(detailsOpenClass).toBe(true);
|
|
21
37
|
});
|
|
22
38
|
|
|
23
39
|
describe('when the details heading is clicked to open the details', () => {
|
|
@@ -26,18 +42,34 @@ describe('script: details', () => {
|
|
|
26
42
|
await page.click('.ons-js-details-heading');
|
|
27
43
|
});
|
|
28
44
|
|
|
29
|
-
it('sets the `open` attribute', async () => {
|
|
30
|
-
const
|
|
31
|
-
|
|
45
|
+
it('sets the `open` attribute and adds the correct class', async () => {
|
|
46
|
+
const detailsOpenClass = await page.$eval('.ons-js-details', (node) => node.classList.contains('ons-details--open'));
|
|
47
|
+
|
|
48
|
+
expect(detailsOpenClass).toBe(true);
|
|
32
49
|
});
|
|
33
50
|
|
|
34
51
|
it('sets the `ga` attributes', async () => {
|
|
35
|
-
const gaHeadingAttribute = await page.$eval('.ons-js-details-heading', element => element.getAttribute('data-ga-action'));
|
|
52
|
+
const gaHeadingAttribute = await page.$eval('.ons-js-details-heading', (element) => element.getAttribute('data-ga-action'));
|
|
36
53
|
|
|
37
54
|
expect(gaHeadingAttribute).toBe('Open panel');
|
|
38
55
|
});
|
|
39
56
|
});
|
|
40
57
|
|
|
58
|
+
describe('when there is more than one details component and a details heading is clicked to open the details', () => {
|
|
59
|
+
beforeEach(async () => {
|
|
60
|
+
await setTestPage('/test', RENDERED_EXAMPLE_PAGE);
|
|
61
|
+
await page.click('#details-id > .ons-js-details-heading');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('sets the `open` attribute and open class on the right component', async () => {
|
|
65
|
+
const detailsOpenClass = await page.$eval('#details-id', (node) => node.classList.contains('ons-details--open'));
|
|
66
|
+
const detailsOpenClass2 = await page.$eval('#details-id-2', (node) => node.classList.contains('ons-details--open'));
|
|
67
|
+
|
|
68
|
+
expect(detailsOpenClass).toBe(true);
|
|
69
|
+
expect(detailsOpenClass2).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
41
73
|
describe('when the details heading is focused', () => {
|
|
42
74
|
beforeEach(async () => {
|
|
43
75
|
await setTestPage('/test', renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
@@ -50,8 +82,8 @@ describe('script: details', () => {
|
|
|
50
82
|
});
|
|
51
83
|
|
|
52
84
|
it('opens the details content', async () => {
|
|
53
|
-
const
|
|
54
|
-
expect(
|
|
85
|
+
const detailsOpenClass = await page.$eval('.ons-js-details', (node) => node.classList.contains('ons-details--open'));
|
|
86
|
+
expect(detailsOpenClass).toBe(true);
|
|
55
87
|
});
|
|
56
88
|
});
|
|
57
89
|
|
|
@@ -61,8 +93,8 @@ describe('script: details', () => {
|
|
|
61
93
|
});
|
|
62
94
|
|
|
63
95
|
it('opens the details content', async () => {
|
|
64
|
-
const
|
|
65
|
-
expect(
|
|
96
|
+
const detailsOpenClass = await page.$eval('.ons-js-details', (node) => node.classList.contains('ons-details--open'));
|
|
97
|
+
expect(detailsOpenClass).toBe(true);
|
|
66
98
|
});
|
|
67
99
|
});
|
|
68
100
|
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{% from "components/details/_macro.njk" import onsDetails %}
|
|
2
2
|
{% from "components/panel/_macro.njk" import onsPanel %}
|
|
3
3
|
|
|
4
|
-
{%
|
|
5
|
-
call onsDetails({
|
|
4
|
+
{% call onsDetails({
|
|
6
5
|
"id": "details-example-with-warning",
|
|
7
6
|
"title": "Need to answer separately from your household?"
|
|
8
7
|
})
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
{% endif %}
|
|
180
180
|
{% if params.copyrightDeclaration %}
|
|
181
181
|
<!-- Copyright -->
|
|
182
|
-
<div class="ons-grid ons-grid--flex ons-grid--vertical-bottom ons-grid--between">
|
|
182
|
+
<div class="ons-grid ons-grid--flex ons-grid--vertical-bottom ons-grid--between">
|
|
183
183
|
<div class="ons-grid__col">
|
|
184
184
|
<p class="ons-u-fs-s ons-u-mb-no ons-footer__copyright">© {{ params.copyrightDeclaration.copyright }} <br> {{ params.copyrightDeclaration.text }}</p>
|
|
185
185
|
</div>
|