Skip to content

Commit 092eb03

Browse files
committed
(#2098) Accordion No Nesting Headers
Closes #2098
1 parent eab7e0a commit 092eb03

File tree

10 files changed

+381
-83
lines changed

10 files changed

+381
-83
lines changed

packages/ncids-js/src/components/usa-accordion/__tests__/example-dom.ts

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export const exampleAccordionPlain = (): HTMLElement => {
22
const div = document.createElement('div');
33

44
div.innerHTML = `
5-
<article class="usa-accordion" id="accEx1">
5+
<article class="usa-accordion" id="accEx1" data-heading-selector="h3">
66
<section class="usa-prose">
77
<h3>this is section header 1 (ex. 1)</h3>
88
<p>this is accordion content.</p>
@@ -43,38 +43,38 @@ export const exampleProseless = (): HTMLElement => {
4343
const div = document.createElement('div');
4444

4545
div.innerHTML = `
46-
<article class="usa-accordion" id="accEx1">
46+
<article class="usa-accordion" id="accEx1" data-heading-selector="h3">
4747
<section>
4848
<h3>this is section header 1 (ex. 1)</h3>
4949
<p>this is accordion content.</p>
50-
<ul>
51-
<li>fake list for content</li>
52-
</ul>
53-
<h4>Header meant to try and break stuff</h4>
54-
<p>
55-
Cuz they do this in content sometimes. this is the real test
56-
</p>
57-
<h3>this is section header 2 (ex. 1)</h3>
58-
<p>This is more content</p>
59-
<ol>
60-
<li>trying out some different content types</li>
61-
</ol>
62-
<h3>this is section header 3 (ex. 1)</h3>
63-
<p>Even more content</p>
64-
<p>
65-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
66-
iaculis fringilla orci eu sagittis. Phasellus sit amet neque
67-
vitae ex molestie condimentum sit amet sed leo.
68-
</p>
69-
<h3>this is section header 4 (ex. 1)</h3>
70-
<p>Even more content</p>
71-
<p>
72-
Donec ullamcorper porta nibh id accumsan. Quisque non ornare
73-
neque, et volutpat dolor. Vestibulum nisi ipsum, sagittis in
74-
ex ac, viverra placerat massa.
75-
</p>
76-
</section>
77-
</article>
50+
<ul>
51+
<li>fake list for content</li>
52+
</ul>
53+
<h4>Header meant to try and break stuff</h4>
54+
<p>
55+
Cuz they do this in content sometimes. this is the real test
56+
</p>
57+
<h3>this is section header 2 (ex. 1)</h3>
58+
<p>This is more content</p>
59+
<ol>
60+
<li>trying out some different content types</li>
61+
</ol>
62+
<h3>this is section header 3 (ex. 1)</h3>
63+
<p>Even more content</p>
64+
<p>
65+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras
66+
iaculis fringilla orci eu sagittis. Phasellus sit amet neque
67+
vitae ex molestie condimentum sit amet sed leo.
68+
</p>
69+
<h3>this is section header 4 (ex. 1)</h3>
70+
<p>Even more content</p>
71+
<p>
72+
Donec ullamcorper porta nibh id accumsan. Quisque non ornare
73+
neque, et volutpat dolor. Vestibulum nisi ipsum, sagittis in
74+
ex ac, viverra placerat massa.
75+
</p>
76+
</section>
77+
</article>
7878
`;
7979

8080
return div;
@@ -84,7 +84,7 @@ export const exampleAccordionBad = (): HTMLElement => {
8484
const div = document.createElement('div');
8585

8686
div.innerHTML = `
87-
<article class="usa-accordion" id="accEx1" data-open-sections="1,2,3">
87+
<article class="usa-accordion" id="accEx1" data-open-sections="1,2,3" data-allow-multiple data-heading-selector="h3">
8888
<section class="usa-prose">
8989
<h3>this is section header 1 (ex. 1)</h3>
9090
<p>this is accordion content.</p>
@@ -125,7 +125,7 @@ export const exampleAccordionInitialized = (): HTMLElement => {
125125
const div = document.createElement('div');
126126

127127
div.innerHTML = `
128-
<div class="usa-accordion " data-open-sections="1">
128+
<div class="usa-accordion" data-open-sections="1">
129129
<h4 class="usa-accordion__heading">
130130
<button class="usa-accordion__button" aria-controls="acc1234" type="button" aria-expanded="true">
131131
First Amendment
@@ -153,3 +153,22 @@ export const exampleAccordionInitialized = (): HTMLElement => {
153153
</div>`;
154154
return div;
155155
};
156+
157+
export const exampleAccordionNoNesting = (): HTMLElement => {
158+
const div = document.createElement('div');
159+
160+
div.innerHTML = `
161+
<div class="cgdp-article-body cgdp-article-body--multiple" data-heading-selector="h2">
162+
<section>
163+
<h2>First Heading</h2>
164+
<p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech</p>
165+
<h2>Inner Heading</h2>
166+
<p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech</p>
167+
</section>
168+
<section>
169+
<h2>Second Section Heading</h2>
170+
<p>Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech</p>
171+
</section>
172+
</div>`;
173+
return div;
174+
};

packages/ncids-js/src/components/usa-accordion/__tests__/usa-accordion.test.ts

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
exampleAccordionBad,
1010
exampleAccordionInitialized,
1111
exampleProseless,
12+
exampleAccordionNoNesting,
1213
} from './example-dom';
1314

1415
describe('USAAccordion', () => {
@@ -17,10 +18,12 @@ describe('USAAccordion', () => {
1718
const options: AccordionOptions = {
1819
allowMultipleOpen: false,
1920
openSections: [1],
21+
headerSelector: '.usa-accordion__header',
2022
};
2123

2224
beforeEach(() => {
23-
container = exampleAccordionPlain();
25+
const wrapper = exampleAccordionPlain();
26+
container = wrapper.querySelector('.usa-accordion') as HTMLElement;
2427
document.body.appendChild(container);
2528
accordion = USAAccordion.create(container, options);
2629
});
@@ -36,19 +39,23 @@ describe('USAAccordion', () => {
3639

3740
it('initializes accordion behavior with existing and styled HTML elements', () => {
3841
document.getElementsByTagName('body')[0].innerHTML = '';
39-
const domContainer = exampleAccordionInitialized();
42+
const wrapper = exampleAccordionInitialized();
43+
const domContainer = wrapper.querySelector('.usa-accordion') as HTMLElement;
4044
document.body.append(domContainer);
4145
accordion = USAAccordion.create(domContainer, options);
4246
expect(accordion).toBeDefined();
4347
expect(container).not.toHaveClass('usa-accordion--multiselectable');
4448
});
4549

46-
it('does not apply usa-prose unless present', async () => {
50+
it('does not apply usa-prose unless present', () => {
4751
document.getElementsByTagName('body')[0].innerHTML = '';
48-
const domContainer = exampleProseless();
52+
53+
const wrapper = exampleProseless();
54+
const domContainer = wrapper.querySelector('.usa-accordion') as HTMLElement;
4955
document.body.append(domContainer);
50-
accordion = USAAccordion.create(domContainer, options);
51-
const content = container.querySelector(
56+
57+
USAAccordion.create(domContainer, options);
58+
const content = domContainer.querySelector(
5259
'.usa-accordion__content'
5360
) as HTMLDivElement;
5461
expect(content).not.toHaveClass('usa-prose');
@@ -58,6 +65,7 @@ describe('USAAccordion', () => {
5865
const customOptions: AccordionOptions = {
5966
allowMultipleOpen: true,
6067
openSections: [1],
68+
headerSelector: '.usa-accordion__header',
6169
};
6270
accordion = USAAccordion.create(container, customOptions);
6371
expect(container).toHaveClass('usa-accordion--multiselectable');
@@ -115,16 +123,17 @@ describe('USAAccordion', () => {
115123
const customOptions: AccordionOptions = {
116124
allowMultipleOpen: true,
117125
openSections: [1],
126+
headerSelector: '.usa-accordion__header',
118127
};
119128
accordion = USAAccordion.create(container, customOptions);
120129
expect(container).toHaveClass('usa-accordion--multiselectable');
121130
accordion.unregister();
122131
expect(container).not.toHaveClass('usa-accordion--multiselectable');
123132
expect(
124-
document.querySelectorAll('usa-accordion__heading').length
133+
document.querySelectorAll('.usa-accordion__heading').length
125134
).toBeFalsy();
126135
expect(
127-
document.querySelectorAll('usa-accordion__content').length
136+
document.querySelectorAll('.usa-accordion__content').length
128137
).toBeFalsy();
129138
});
130139

@@ -141,4 +150,27 @@ describe('USAAccordion', () => {
141150
await user.click(button);
142151
expect(controlledSection!.hidden).toBeTruthy();
143152
});
153+
154+
it('does not convert inner headings into buttons', async () => {
155+
Object.defineProperty(window, 'innerWidth', {
156+
writable: true,
157+
configurable: true,
158+
value: 375,
159+
});
160+
161+
const domContainer = exampleAccordionNoNesting();
162+
document.body.append(domContainer);
163+
const newOptions = {
164+
...options,
165+
headerSelector: '.cgdp-article-body__heading',
166+
};
167+
USAAccordion.create(domContainer, newOptions);
168+
169+
window.dispatchEvent(new Event('resize'));
170+
171+
const allHeadings = document.body.querySelectorAll('h2');
172+
const innerHeading = allHeadings[1];
173+
174+
expect(innerHeading.querySelector('button')).toBeNull();
175+
});
144176
});

packages/ncids-js/src/components/usa-accordion/usa-accordion-options.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ export type AccordionOptions = {
77
allowMultipleOpen: boolean;
88
/** specifies sections opened at init. */
99
openSections: Array<number>;
10+
/** header selector for accordion buttons */
11+
headerSelector: string;
1012
};

0 commit comments

Comments
 (0)