@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% macro onsAccordion(params) %}
|
|
2
|
-
{% from "components/
|
|
2
|
+
{% from "components/details/_macro.njk" import onsDetails %}
|
|
3
3
|
|
|
4
4
|
<div id="{{params.id}}" class="ons-accordion{{ ' ' + params.classes if params.classes }}">
|
|
5
5
|
{% if params.allButton %}
|
|
@@ -24,10 +24,9 @@
|
|
|
24
24
|
{% endif %}
|
|
25
25
|
{% for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) %}
|
|
26
26
|
{{
|
|
27
|
-
|
|
27
|
+
onsDetails({
|
|
28
28
|
"isAccordion": true,
|
|
29
29
|
"id": params.id + "-" + (loop.index | string),
|
|
30
|
-
"button": item.button,
|
|
31
30
|
"attributes": item.attributes,
|
|
32
31
|
"headingAttributes": item.headingAttributes,
|
|
33
32
|
"contentAttributes": item.contentAttributes,
|
|
@@ -57,7 +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-
|
|
60
|
+
const titleText = $('.ons-details__title')
|
|
61
61
|
.first()
|
|
62
62
|
.text()
|
|
63
63
|
.trim();
|
|
@@ -77,14 +77,14 @@ describe('macro: accordion', () => {
|
|
|
77
77
|
}),
|
|
78
78
|
);
|
|
79
79
|
|
|
80
|
-
const titleTag = $('.ons-
|
|
80
|
+
const titleTag = $('.ons-details__title')[0].tagName;
|
|
81
81
|
expect(titleTag).toBe('h5');
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
it('has provided content text', () => {
|
|
85
85
|
const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
|
|
86
86
|
|
|
87
|
-
const titleText = $('.ons-
|
|
87
|
+
const titleText = $('.ons-details__content')
|
|
88
88
|
.first()
|
|
89
89
|
.text()
|
|
90
90
|
.trim();
|
|
@@ -106,8 +106,8 @@ describe('macro: accordion', () => {
|
|
|
106
106
|
}),
|
|
107
107
|
);
|
|
108
108
|
|
|
109
|
-
expect($('.ons-
|
|
110
|
-
expect($('.ons-
|
|
109
|
+
expect($('.ons-details').attr('a')).toBe('123');
|
|
110
|
+
expect($('.ons-details').attr('b')).toBe('456');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
it('has additionally provided `headingAttributes`', () => {
|
|
@@ -125,8 +125,8 @@ describe('macro: accordion', () => {
|
|
|
125
125
|
}),
|
|
126
126
|
);
|
|
127
127
|
|
|
128
|
-
expect($('.ons-
|
|
129
|
-
expect($('.ons-
|
|
128
|
+
expect($('.ons-details__heading').attr('a')).toBe('123');
|
|
129
|
+
expect($('.ons-details__heading').attr('b')).toBe('456');
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
it('has additionally provided `contentAttributes`', () => {
|
|
@@ -145,8 +145,8 @@ describe('macro: accordion', () => {
|
|
|
145
145
|
}),
|
|
146
146
|
);
|
|
147
147
|
|
|
148
|
-
expect($('.ons-
|
|
149
|
-
expect($('.ons-
|
|
148
|
+
expect($('.ons-details__content').attr('a')).toBe('123');
|
|
149
|
+
expect($('.ons-details__content').attr('b')).toBe('456');
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
152
|
|
|
@@ -4,14 +4,14 @@ async function initialiseAccordions() {
|
|
|
4
4
|
const toggleAllButtons = [...document.querySelectorAll('.ons-js-accordion-all')];
|
|
5
5
|
|
|
6
6
|
if (toggleAllButtons.length) {
|
|
7
|
-
const
|
|
7
|
+
const detailsComponents = [...document.querySelectorAll('.ons-js-details')];
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const Details = (await import('../details/details')).default;
|
|
10
10
|
const Accordion = (await import('./accordion')).default;
|
|
11
|
-
const
|
|
11
|
+
const detailsEls = detailsComponents.map(element => new Details(element));
|
|
12
12
|
|
|
13
13
|
toggleAllButtons.forEach(button => {
|
|
14
|
-
new Accordion(button,
|
|
14
|
+
new Accordion(button, detailsEls);
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
export default class Accordion {
|
|
2
|
-
constructor(button,
|
|
3
|
-
this.
|
|
2
|
+
constructor(button, detailsEls) {
|
|
3
|
+
this.openDetailsEls = 0;
|
|
4
4
|
|
|
5
5
|
this.button = button;
|
|
6
6
|
this.buttonInner = button.querySelector('.ons-js-accordion-all-inner');
|
|
7
7
|
this.group = button.getAttribute('data-group');
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
8
|
+
this.detailsEls = detailsEls.filter(details => details.group === this.group);
|
|
9
|
+
this.totalDetailsEls = this.detailsEls.length;
|
|
10
10
|
this.buttonOpenEl = this.buttonInner.querySelector('.ons-btn__text');
|
|
11
11
|
this.buttonOpen = this.buttonOpenEl.innerHTML.trim();
|
|
12
12
|
this.closeButton = button.getAttribute('data-close-all');
|
|
13
|
-
this.open = this.
|
|
13
|
+
this.open = this.detailsEls.find(details => details.open === true);
|
|
14
14
|
|
|
15
|
-
this.
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
this.detailsEls.forEach(details => {
|
|
16
|
+
details.onOpen = this.onOpen.bind(this);
|
|
17
|
+
details.onClose = this.onClose.bind(this);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
if (this.open) {
|
|
21
|
-
this.
|
|
21
|
+
this.openDetailsEls = this.totalDetailsEls;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
this.button.addEventListener('click', this.handleButtonClick.bind(this));
|
|
@@ -31,23 +31,23 @@ export default class Accordion {
|
|
|
31
31
|
|
|
32
32
|
const open = !this.canClose();
|
|
33
33
|
|
|
34
|
-
this.
|
|
35
|
-
|
|
34
|
+
this.detailsEls.forEach(details => {
|
|
35
|
+
details.setOpen(open);
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
onOpen() {
|
|
40
|
-
this.
|
|
40
|
+
this.openDetailsEls++;
|
|
41
41
|
this.setButton();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
onClose() {
|
|
45
|
-
this.
|
|
45
|
+
this.openDetailsEls--;
|
|
46
46
|
this.setButton();
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
canClose() {
|
|
50
|
-
return this.
|
|
50
|
+
return this.openDetailsEls === this.totalDetailsEls;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
setButton() {
|
|
@@ -39,7 +39,7 @@ describe('script: accordion', () => {
|
|
|
39
39
|
}),
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
const openElements = await page.$$eval('.ons-js-
|
|
42
|
+
const openElements = await page.$$eval('.ons-js-details', nodes => nodes.filter(node => node.open));
|
|
43
43
|
expect(openElements[0]).not.toBe(undefined);
|
|
44
44
|
expect(openElements[1]).not.toBe(undefined);
|
|
45
45
|
expect(openElements[2]).not.toBe(undefined);
|
|
@@ -76,7 +76,7 @@ describe('script: accordion', () => {
|
|
|
76
76
|
|
|
77
77
|
await page.click('button[data-test-trigger]');
|
|
78
78
|
|
|
79
|
-
const openElements = await page.$$eval('.ons-js-
|
|
79
|
+
const openElements = await page.$$eval('.ons-js-details', nodes => nodes.filter(node => node.open));
|
|
80
80
|
expect(openElements[0]).not.toBe(undefined);
|
|
81
81
|
expect(openElements[1]).not.toBe(undefined);
|
|
82
82
|
expect(openElements[2]).not.toBe(undefined);
|
|
@@ -88,7 +88,7 @@ describe('script: accordion', () => {
|
|
|
88
88
|
await page.click('button[data-test-trigger]');
|
|
89
89
|
await page.click('button[data-test-trigger]');
|
|
90
90
|
|
|
91
|
-
const openElements = await page.$$eval('.ons-js-
|
|
91
|
+
const openElements = await page.$$eval('.ons-js-details', nodes => nodes.filter(node => node.open));
|
|
92
92
|
expect(openElements[0]).toBe(undefined);
|
|
93
93
|
expect(openElements[1]).toBe(undefined);
|
|
94
94
|
expect(openElements[2]).toBe(undefined);
|
|
@@ -129,9 +129,9 @@ describe('script: accordion', () => {
|
|
|
129
129
|
it('sets toggle all button label to "Hide all" when all items are shown', async () => {
|
|
130
130
|
await setTestPage('/test', renderComponent('accordion', EXAMPLE_ACCORDION_WITH_ALL_BUTTON));
|
|
131
131
|
|
|
132
|
-
await page.click('#example-accordion-1 .ons-
|
|
133
|
-
await page.click('#example-accordion-2 .ons-
|
|
134
|
-
await page.click('#example-accordion-3 .ons-
|
|
132
|
+
await page.click('#example-accordion-1 .ons-details__heading');
|
|
133
|
+
await page.click('#example-accordion-2 .ons-details__heading');
|
|
134
|
+
await page.click('#example-accordion-3 .ons-details__heading');
|
|
135
135
|
|
|
136
136
|
const buttonText = await page.$eval('button[data-test-trigger]', element => element.innerText);
|
|
137
137
|
expect(buttonText.trim()).toBe('Close all');
|
|
@@ -1,30 +1,22 @@
|
|
|
1
|
+
{# OnsCollapsible has been superceded by onsDetails and will be deprecated in due course. Please upgrade to use onsDetails. Configuration is unchanged, only the component name and classes have changed name. #}
|
|
1
2
|
{% macro onsCollapsible(params) %}
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
})
|
|
22
|
-
}}</span>
|
|
23
|
-
</summary>
|
|
24
|
-
<div id="{{ params.id }}-content" class="ons-collapsible__content ons-js-collapsible-content"
|
|
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
|
-
>
|
|
27
|
-
{{ params.content | safe }}{{ caller() if caller }}
|
|
28
|
-
</div>
|
|
29
|
-
</details>
|
|
3
|
+
{% from "components/details/_macro.njk" import onsDetails %}
|
|
4
|
+
|
|
5
|
+
{% set content = caller() if caller else params.content | safe %}
|
|
6
|
+
|
|
7
|
+
{{
|
|
8
|
+
onsDetails({
|
|
9
|
+
"id": params.id,
|
|
10
|
+
"classes": params.classes,
|
|
11
|
+
"attributes": params.attributes,
|
|
12
|
+
"headingAttributes": params.headingAttributes,
|
|
13
|
+
"contentAttributes": params.contentAttributes,
|
|
14
|
+
"title": params.title,
|
|
15
|
+
"titleTag": params.titleTag,
|
|
16
|
+
"content": content,
|
|
17
|
+
"saveState": params.saveState,
|
|
18
|
+
"open": params.open
|
|
19
|
+
})
|
|
20
|
+
}}
|
|
21
|
+
|
|
30
22
|
{% endmacro %}
|
|
@@ -22,7 +22,7 @@ describe('macro: collapsible', () => {
|
|
|
22
22
|
it('has the provided `id` attribute', () => {
|
|
23
23
|
const $ = cheerio.load(renderComponent('collapsible', EXAMPLE_COLLAPSIBLE_BASIC));
|
|
24
24
|
|
|
25
|
-
expect($('.ons-
|
|
25
|
+
expect($('.ons-details').attr('id')).toBe('collapsible-id');
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('has additionally provided style classes', () => {
|
|
@@ -33,14 +33,14 @@ describe('macro: collapsible', () => {
|
|
|
33
33
|
}),
|
|
34
34
|
);
|
|
35
35
|
|
|
36
|
-
expect($('.ons-
|
|
37
|
-
expect($('.ons-
|
|
36
|
+
expect($('.ons-details').hasClass('extra-class')).toBe(true);
|
|
37
|
+
expect($('.ons-details').hasClass('another-extra-class')).toBe(true);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it('has provided title text', () => {
|
|
41
41
|
const $ = cheerio.load(renderComponent('collapsible', EXAMPLE_COLLAPSIBLE_BASIC));
|
|
42
42
|
|
|
43
|
-
const titleText = $('.ons-
|
|
43
|
+
const titleText = $('.ons-details__title')
|
|
44
44
|
.first()
|
|
45
45
|
.text()
|
|
46
46
|
.trim();
|
|
@@ -55,14 +55,14 @@ describe('macro: collapsible', () => {
|
|
|
55
55
|
}),
|
|
56
56
|
);
|
|
57
57
|
|
|
58
|
-
const titleTag = $('.ons-
|
|
58
|
+
const titleTag = $('.ons-details__title')[0].tagName;
|
|
59
59
|
expect(titleTag).toBe('h4');
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
it('has provided content text', () => {
|
|
63
63
|
const $ = cheerio.load(renderComponent('collapsible', EXAMPLE_COLLAPSIBLE_BASIC));
|
|
64
64
|
|
|
65
|
-
const titleText = $('.ons-
|
|
65
|
+
const titleText = $('.ons-details__content')
|
|
66
66
|
.text()
|
|
67
67
|
.trim();
|
|
68
68
|
expect(titleText).toEqual(expect.stringContaining('Content for collapsible'));
|
|
@@ -78,8 +78,8 @@ describe('macro: collapsible', () => {
|
|
|
78
78
|
},
|
|
79
79
|
}),
|
|
80
80
|
);
|
|
81
|
-
expect($('.ons-
|
|
82
|
-
expect($('.ons-
|
|
81
|
+
expect($('.ons-details').attr('a')).toBe('123');
|
|
82
|
+
expect($('.ons-details').attr('b')).toBe('456');
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
it('has the correct data attribute when `saveState` is provided', () => {
|
|
@@ -89,7 +89,7 @@ describe('macro: collapsible', () => {
|
|
|
89
89
|
saveState: true,
|
|
90
90
|
}),
|
|
91
91
|
);
|
|
92
|
-
expect($('.ons-
|
|
92
|
+
expect($('.ons-details').attr('data-save-state')).toBe('true');
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('has the correct data attribute when `open` is provided', () => {
|
|
@@ -99,7 +99,7 @@ describe('macro: collapsible', () => {
|
|
|
99
99
|
open: true,
|
|
100
100
|
}),
|
|
101
101
|
);
|
|
102
|
-
expect($('.ons-
|
|
102
|
+
expect($('.ons-details').attr('data-open')).toBe('true');
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
it('has additionally provided `headingAttributes`', () => {
|
|
@@ -113,8 +113,8 @@ describe('macro: collapsible', () => {
|
|
|
113
113
|
}),
|
|
114
114
|
);
|
|
115
115
|
|
|
116
|
-
expect($('.ons-
|
|
117
|
-
expect($('.ons-
|
|
116
|
+
expect($('.ons-details__heading').attr('a')).toBe('123');
|
|
117
|
+
expect($('.ons-details__heading').attr('b')).toBe('456');
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
it('has additionally provided `contentAttributes`', () => {
|
|
@@ -128,8 +128,8 @@ describe('macro: collapsible', () => {
|
|
|
128
128
|
}),
|
|
129
129
|
);
|
|
130
130
|
|
|
131
|
-
expect($('.ons-
|
|
132
|
-
expect($('.ons-
|
|
131
|
+
expect($('.ons-details__content').attr('a')).toBe('123');
|
|
132
|
+
expect($('.ons-details__content').attr('b')).toBe('456');
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
it('has `chevron` icon', () => {
|
|
@@ -143,7 +143,7 @@ describe('macro: collapsible', () => {
|
|
|
143
143
|
it('calls with content', () => {
|
|
144
144
|
const $ = cheerio.load(renderComponent('collapsible', { EXAMPLE_COLLAPSIBLE_BASIC }, 'Example content...'));
|
|
145
145
|
|
|
146
|
-
const content = $('.ons-
|
|
146
|
+
const content = $('.ons-details__content')
|
|
147
147
|
.text()
|
|
148
148
|
.trim();
|
|
149
149
|
expect(content).toEqual(expect.stringContaining('Example content...'));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
$
|
|
1
|
+
$details-caret-width: 1.5rem;
|
|
2
2
|
|
|
3
|
-
.ons-
|
|
3
|
+
.ons-details {
|
|
4
4
|
&__heading {
|
|
5
5
|
color: var(--ons-color-text-link);
|
|
6
6
|
cursor: pointer;
|
|
7
7
|
display: inline-block;
|
|
8
8
|
outline: none;
|
|
9
|
-
padding: 0 0 0 $
|
|
9
|
+
padding: 0 0 0 $details-caret-width;
|
|
10
10
|
pointer-events: initial;
|
|
11
11
|
position: relative;
|
|
12
12
|
|
|
@@ -16,23 +16,23 @@ $collapsible-caret-width: 1.5rem;
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
&:focus {
|
|
19
|
-
.ons-
|
|
19
|
+
.ons-details__title {
|
|
20
20
|
@extend %a-focus;
|
|
21
|
-
// extend
|
|
22
|
-
margin-left: -$
|
|
23
|
-
padding-left: $
|
|
21
|
+
// extend details focus background behind caret
|
|
22
|
+
margin-left: -$details-caret-width;
|
|
23
|
+
padding-left: $details-caret-width;
|
|
24
24
|
}
|
|
25
|
-
.ons-
|
|
25
|
+
.ons-details__icon .ons-svg-icon {
|
|
26
26
|
fill: var(--ons-color-text-link-focus);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
&:hover:not(:focus) {
|
|
31
31
|
color: var(--ons-color-text-link-hover);
|
|
32
|
-
.ons-
|
|
32
|
+
.ons-details__icon {
|
|
33
33
|
fill: var(--ons-color-text-link-hover);
|
|
34
34
|
}
|
|
35
|
-
.ons-
|
|
35
|
+
.ons-details__title {
|
|
36
36
|
text-decoration: underline solid var(--ons-color-text-link-hover) 2px;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -41,11 +41,11 @@ $collapsible-caret-width: 1.5rem;
|
|
|
41
41
|
&__icon {
|
|
42
42
|
display: inline-block;
|
|
43
43
|
fill: var(--ons-color-text-link);
|
|
44
|
-
height: $
|
|
44
|
+
height: $details-caret-width;
|
|
45
45
|
left: -0.15rem;
|
|
46
46
|
position: absolute;
|
|
47
47
|
top: -0.2rem;
|
|
48
|
-
width: $
|
|
48
|
+
width: $details-caret-width;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
&__title {
|
|
@@ -112,9 +112,9 @@ $collapsible-caret-width: 1.5rem;
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
.ons-
|
|
115
|
+
.ons-details--accordion {
|
|
116
116
|
&[open] {
|
|
117
|
-
.ons-
|
|
117
|
+
.ons-details__icon {
|
|
118
118
|
top: 1.2rem;
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{% macro onsDetails(params) %}
|
|
2
|
+
<details
|
|
3
|
+
id="{{ params.id }}"
|
|
4
|
+
class="ons-details ons-js-details{% if params.isAccordion %} ons-details--accordion{% endif %}{% if params.classes %} {{ params.classes }}{% endif %}"
|
|
5
|
+
{% if params.group %} data-group="{{ params.group }}"{% endif %}
|
|
6
|
+
{% if params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %}{{ attribute }}{% if value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
|
|
7
|
+
{% if params.saveState %} data-save-state="true"{% endif %}
|
|
8
|
+
{% if params.open %} data-open="true"{% endif %}
|
|
9
|
+
>
|
|
10
|
+
<summary
|
|
11
|
+
class="ons-details__heading ons-js-details-heading"
|
|
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
|
+
>
|
|
14
|
+
{% set titleTag = params.titleTag | default("h2") %}
|
|
15
|
+
<{{ titleTag }} class="ons-details__title">{{ params.title }}</{{ titleTag }}>
|
|
16
|
+
<span class="ons-details__icon">
|
|
17
|
+
{% from "components/icons/_macro.njk" import onsIcon %}
|
|
18
|
+
{{
|
|
19
|
+
onsIcon({
|
|
20
|
+
"iconType": "chevron"
|
|
21
|
+
})
|
|
22
|
+
}}</span>
|
|
23
|
+
</summary>
|
|
24
|
+
<div id="{{ params.id }}-content" class="ons-details__content ons-js-details-content"
|
|
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
|
+
>
|
|
27
|
+
{{ params.content | safe }}{{ caller() if caller }}
|
|
28
|
+
</div>
|
|
29
|
+
</details>
|
|
30
|
+
{% endmacro %}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/** @jest-environment jsdom */
|
|
2
|
+
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
|
|
5
|
+
import axe from '../../tests/helpers/axe';
|
|
6
|
+
import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
|
|
7
|
+
|
|
8
|
+
const EXAMPLE_DETAILS_BASIC = {
|
|
9
|
+
id: 'details-id',
|
|
10
|
+
title: 'Title for details',
|
|
11
|
+
content: 'Content for details',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
describe('macro: details', () => {
|
|
15
|
+
it('passes jest-axe checks', async () => {
|
|
16
|
+
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
17
|
+
|
|
18
|
+
const results = await axe($.html());
|
|
19
|
+
expect(results).toHaveNoViolations();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('has the provided `id` attribute', () => {
|
|
23
|
+
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
24
|
+
|
|
25
|
+
expect($('.ons-details').attr('id')).toBe('details-id');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('has additionally provided style classes', () => {
|
|
29
|
+
const $ = cheerio.load(
|
|
30
|
+
renderComponent('details', {
|
|
31
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
32
|
+
classes: 'extra-class another-extra-class',
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
expect($('.ons-details').hasClass('extra-class')).toBe(true);
|
|
37
|
+
expect($('.ons-details').hasClass('another-extra-class')).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('has provided title text', () => {
|
|
41
|
+
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
42
|
+
|
|
43
|
+
const titleText = $('.ons-details__title')
|
|
44
|
+
.first()
|
|
45
|
+
.text()
|
|
46
|
+
.trim();
|
|
47
|
+
expect(titleText).toBe('Title for details');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('has title with provided tag override', () => {
|
|
51
|
+
const $ = cheerio.load(
|
|
52
|
+
renderComponent('details', {
|
|
53
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
54
|
+
titleTag: 'h4',
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const titleTag = $('.ons-details__title')[0].tagName;
|
|
59
|
+
expect(titleTag).toBe('h4');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('has provided content text', () => {
|
|
63
|
+
const $ = cheerio.load(renderComponent('details', EXAMPLE_DETAILS_BASIC));
|
|
64
|
+
|
|
65
|
+
const titleText = $('.ons-details__content')
|
|
66
|
+
.text()
|
|
67
|
+
.trim();
|
|
68
|
+
expect(titleText).toEqual(expect.stringContaining('Content for details'));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('has additionally provided `attributes`', () => {
|
|
72
|
+
const $ = cheerio.load(
|
|
73
|
+
renderComponent('details', {
|
|
74
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
75
|
+
attributes: {
|
|
76
|
+
a: 123,
|
|
77
|
+
b: 456,
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
expect($('.ons-details').attr('a')).toBe('123');
|
|
82
|
+
expect($('.ons-details').attr('b')).toBe('456');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('has the correct data attribute when `saveState` is provided', () => {
|
|
86
|
+
const $ = cheerio.load(
|
|
87
|
+
renderComponent('details', {
|
|
88
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
89
|
+
saveState: true,
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
expect($('.ons-details').attr('data-save-state')).toBe('true');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('has the correct data attribute when `open` is provided', () => {
|
|
96
|
+
const $ = cheerio.load(
|
|
97
|
+
renderComponent('details', {
|
|
98
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
99
|
+
open: true,
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
expect($('.ons-details').attr('data-open')).toBe('true');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('has additionally provided `headingAttributes`', () => {
|
|
106
|
+
const $ = cheerio.load(
|
|
107
|
+
renderComponent('details', {
|
|
108
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
109
|
+
headingAttributes: {
|
|
110
|
+
a: 123,
|
|
111
|
+
b: 456,
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect($('.ons-details__heading').attr('a')).toBe('123');
|
|
117
|
+
expect($('.ons-details__heading').attr('b')).toBe('456');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('has additionally provided `contentAttributes`', () => {
|
|
121
|
+
const $ = cheerio.load(
|
|
122
|
+
renderComponent('details', {
|
|
123
|
+
...EXAMPLE_DETAILS_BASIC,
|
|
124
|
+
contentAttributes: {
|
|
125
|
+
a: 123,
|
|
126
|
+
b: 456,
|
|
127
|
+
},
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect($('.ons-details__content').attr('a')).toBe('123');
|
|
132
|
+
expect($('.ons-details__content').attr('b')).toBe('456');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('has `chevron` icon', () => {
|
|
136
|
+
const faker = templateFaker();
|
|
137
|
+
const iconsSpy = faker.spy('icons');
|
|
138
|
+
faker.renderComponent('details', EXAMPLE_DETAILS_BASIC);
|
|
139
|
+
|
|
140
|
+
expect(iconsSpy.occurrences[0].iconType).toBe('chevron');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('calls with content', () => {
|
|
144
|
+
const $ = cheerio.load(renderComponent('details', { EXAMPLE_DETAILS_BASIC }, 'Example content...'));
|
|
145
|
+
|
|
146
|
+
const content = $('.ons-details__content')
|
|
147
|
+
.text()
|
|
148
|
+
.trim();
|
|
149
|
+
expect(content).toEqual(expect.stringContaining('Example content...'));
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import domready from '../../js/domready';
|
|
2
|
+
|
|
3
|
+
async function initialiseDetailsEls() {
|
|
4
|
+
const detailsComponents = [...document.querySelectorAll('.ons-js-details')];
|
|
5
|
+
const accordionComponents = [...document.querySelectorAll('.ons-js-accordion')];
|
|
6
|
+
|
|
7
|
+
if (detailsComponents.length && !accordionComponents.length) {
|
|
8
|
+
const Details = (await import('./details')).default;
|
|
9
|
+
detailsComponents.map(element => new Details(element));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
domready(initialiseDetailsEls);
|