Skip to content

Commit 433eade

Browse files
authored
Merge pull request #393 from 4site-interactive-studios/enhanced-accessibility
Accessibility Improvements: Click-to-Expand
2 parents 3369e80 + c6103e8 commit 433eade

5 files changed

Lines changed: 152 additions & 60 deletions

File tree

packages/scripts/dist/click-to-expand.js

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,60 @@ export class ClickToExpand {
66
constructor() {
77
this.clickToExpandWrapper = document.querySelectorAll("div.click-to-expand");
88
if (this.clickToExpandWrapper.length) {
9-
this.clickToExpandWrapper.forEach((element) => {
10-
const content = element.innerHTML;
11-
const wrapper_html = '<div class="click-to-expand-cta"></div><div class="click-to-expand-text-wrapper" tabindex="0">' +
12-
content +
13-
"</div>";
14-
element.innerHTML = wrapper_html;
15-
element.addEventListener("click", (event) => {
16-
if (event) {
17-
if (ENGrid.debug)
18-
console.log("A click-to-expand div was clicked");
19-
element.classList.add("expanded");
9+
this.clickToExpandWrapper.forEach((element, index) => {
10+
var _a;
11+
const textWrapperId = `click-to-expand-text-${index}`;
12+
const ctaId = `click-to-expand-cta-${index}`;
13+
// Extract screen reader tip from the live DOM
14+
const screenReaderTip = element.querySelector(".click-to-expand-screenreader-tip");
15+
let ariaLabel = "Show more";
16+
if (screenReaderTip) {
17+
const tipText = (_a = screenReaderTip.textContent) === null || _a === void 0 ? void 0 : _a.trim();
18+
if (tipText) {
19+
ariaLabel = `Show more: ${tipText}`;
2020
}
21+
screenReaderTip.remove();
22+
}
23+
// Capture all original child nodes before restructuring
24+
const originalChildren = Array.from(element.childNodes);
25+
element.innerHTML = "";
26+
// Create the text wrapper
27+
const textWrapper = document.createElement("div");
28+
textWrapper.className = "click-to-expand-text-wrapper";
29+
textWrapper.id = textWrapperId;
30+
textWrapper.setAttribute("aria-hidden", "true");
31+
textWrapper.setAttribute("aria-label", "Expanded content" + (ariaLabel ? `${ariaLabel.replace('Show more', '')}` : ""));
32+
textWrapper.setAttribute("tabindex", "-1");
33+
originalChildren.forEach((child) => {
34+
textWrapper.appendChild(child);
2135
});
36+
const cta = document.createElement("div");
37+
cta.className = "click-to-expand-cta";
38+
cta.id = ctaId;
39+
cta.setAttribute("role", "button");
40+
cta.setAttribute("tabindex", "0");
41+
cta.setAttribute("aria-expanded", "false");
42+
cta.setAttribute("aria-controls", textWrapperId);
43+
cta.setAttribute("aria-label", ariaLabel);
44+
element.appendChild(textWrapper);
45+
element.appendChild(cta);
46+
const expand = () => {
47+
if (ENGrid.debug) {
48+
console.log("A click-to-expand div was expanded");
49+
}
50+
element.classList.add("expanded");
51+
cta.setAttribute("aria-expanded", "true");
52+
cta.setAttribute("aria-hidden", "true");
53+
textWrapper.setAttribute("aria-hidden", "false");
54+
textWrapper.focus(); // Move focus to revealed content for screen reader announcement
55+
};
56+
element.addEventListener("click", expand);
2257
element.addEventListener("keydown", (event) => {
2358
if (event.key === "Enter") {
24-
if (ENGrid.debug)
25-
console.log("A click-to-expand div had the 'Enter' key pressed on it");
26-
element.classList.add("expanded");
59+
expand();
2760
}
2861
else if (event.key === " ") {
29-
if (ENGrid.debug)
30-
console.log("A click-to-expand div had the 'Spacebar' key pressed on it");
31-
element.classList.add("expanded");
62+
expand();
3263
event.preventDefault(); // Prevents the page from scrolling
3364
event.stopPropagation(); // Prevent a console error generated by LastPass https://github.com/KillerCodeMonkey/ngx-quill/issues/351#issuecomment-476017960
3465
}

packages/scripts/src/click-to-expand.ts

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,69 @@ export class ClickToExpand {
1111

1212
constructor() {
1313
if (this.clickToExpandWrapper.length) {
14-
this.clickToExpandWrapper.forEach((element: HTMLElement) => {
15-
const content = element.innerHTML;
16-
const wrapper_html =
17-
'<div class="click-to-expand-cta"></div><div class="click-to-expand-text-wrapper" tabindex="0">' +
18-
content +
19-
"</div>";
20-
element.innerHTML = wrapper_html;
21-
element.addEventListener("click", (event) => {
22-
if (event) {
23-
if (ENGrid.debug) console.log("A click-to-expand div was clicked");
24-
element.classList.add("expanded");
14+
this.clickToExpandWrapper.forEach((element: HTMLElement, index: number) => {
15+
const textWrapperId = `click-to-expand-text-${index}`;
16+
const ctaId = `click-to-expand-cta-${index}`;
17+
18+
// Extract screen reader tip from the live DOM
19+
const screenReaderTip = element.querySelector(
20+
".click-to-expand-screenreader-tip"
21+
);
22+
let ariaLabel = "Show more";
23+
if (screenReaderTip) {
24+
const tipText = screenReaderTip.textContent?.trim();
25+
if (tipText) {
26+
ariaLabel = `Show more: ${tipText}`;
2527
}
28+
screenReaderTip.remove();
29+
}
30+
31+
// Capture all original child nodes before restructuring
32+
const originalChildren = Array.from(element.childNodes);
33+
34+
element.innerHTML = "";
35+
36+
// Create the text wrapper
37+
const textWrapper = document.createElement("div");
38+
textWrapper.className = "click-to-expand-text-wrapper";
39+
textWrapper.id = textWrapperId;
40+
textWrapper.setAttribute("aria-hidden", "true");
41+
textWrapper.setAttribute("aria-label", "Expanded content" + (ariaLabel ? `${ariaLabel.replace('Show more', '')}` : ""));
42+
textWrapper.setAttribute("tabindex", "-1");
43+
44+
originalChildren.forEach((child) => {
45+
textWrapper.appendChild(child);
2646
});
2747

48+
const cta = document.createElement("div");
49+
cta.className = "click-to-expand-cta";
50+
cta.id = ctaId;
51+
cta.setAttribute("role", "button");
52+
cta.setAttribute("tabindex", "0");
53+
cta.setAttribute("aria-expanded", "false");
54+
cta.setAttribute("aria-controls", textWrapperId);
55+
cta.setAttribute("aria-label", ariaLabel);
56+
57+
element.appendChild(textWrapper);
58+
element.appendChild(cta);
59+
60+
const expand = () => {
61+
if (ENGrid.debug) {
62+
console.log("A click-to-expand div was expanded");
63+
}
64+
element.classList.add("expanded");
65+
cta.setAttribute("aria-expanded", "true");
66+
cta.setAttribute("aria-hidden", "true");
67+
textWrapper.setAttribute("aria-hidden", "false");
68+
textWrapper.focus(); // Move focus to revealed content for screen reader announcement
69+
};
70+
71+
element.addEventListener("click", expand);
2872
element.addEventListener("keydown", (event) => {
2973
if ((event as KeyboardEvent).key === "Enter") {
30-
if (ENGrid.debug)
31-
console.log(
32-
"A click-to-expand div had the 'Enter' key pressed on it"
33-
);
34-
element.classList.add("expanded");
74+
expand();
3575
} else if ((event as KeyboardEvent).key === " ") {
36-
if (ENGrid.debug)
37-
console.log(
38-
"A click-to-expand div had the 'Spacebar' key pressed on it"
39-
);
40-
element.classList.add("expanded");
76+
expand();
4177
event.preventDefault(); // Prevents the page from scrolling
4278
event.stopPropagation(); // Prevent a console error generated by LastPass https://github.com/KillerCodeMonkey/ngx-quill/issues/351#issuecomment-476017960
4379
}

packages/styles/dist/main.css

Lines changed: 18 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/styles/dist/main.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/styles/src/_engrid-click-to-expand.scss

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@
66
--click-to-expand__cta-image_height: 16px;
77
}
88

9+
body#en__pagebuilder {
10+
.click-to-expand-screenreader-tip {
11+
background-color: #f8a8091a !important;
12+
}
13+
}
14+
915
// Depends on click-to-expand.ts
10-
body:not(#en__pagebuilder)
11-
.click-to-expand
12-
.click-to-expand-text-wrapper
13-
> :first-child {
16+
body:not(#en__pagebuilder) .click-to-expand .click-to-expand-text-wrapper> :first-child {
1417
margin-top: 0;
1518
}
1619

20+
body:not(#en__pagebuilder) .click-to-expand .click-to-expand-screenreader-tip {
21+
display: none;
22+
}
23+
1724
body:not(#en__pagebuilder) .click-to-expand:not(.expanded) {
1825
overflow: hidden; // Prevents content from extending beyond the visible area of the unexpanded click-to-expand section https://d.pr/v/4tc9u2
1926
cursor: pointer;
@@ -23,24 +30,17 @@ body:not(#en__pagebuilder) .click-to-expand:not(.expanded) {
2330
// Works with transparent backgrounds for when the ENgrid is in its embedded state
2431
// REF: https://stackoverflow.com/a/58740440/815683
2532
.click-to-expand-text-wrapper {
26-
max-height: calc(
27-
var(--click-to-expand__copy-area_height) -
28-
var(--click-to-expand__cta-image_height) - 35px
29-
);
30-
mask-image: linear-gradient(
31-
to bottom,
32-
black 50%,
33-
rgba(255, 255, 255, 0)
34-
calc(100% - var(--click-to-expand__cta-image_height))
35-
);
33+
max-height: calc(var(--click-to-expand__copy-area_height) - var(--click-to-expand__cta-image_height) - 35px);
34+
mask-image: linear-gradient(to bottom,
35+
black 50%,
36+
rgba(255, 255, 255, 0) calc(100% - var(--click-to-expand__cta-image_height)));
3637
}
3738

3839
.click-to-expand-cta {
3940
background: var(--click-to-expand__cta-image_url);
4041
background-position: center bottom;
4142
background-repeat: no-repeat;
42-
background-size: var(--click-to-expand__cta-image_width)
43-
var(--click-to-expand__cta-image_height);
43+
background-size: var(--click-to-expand__cta-image_width) var(--click-to-expand__cta-image_height);
4444
// z-index: 100;
4545
width: var(--click-to-expand__cta-image_width);
4646
height: var(--click-to-expand__cta-image_height);
@@ -50,11 +50,20 @@ body:not(#en__pagebuilder) .click-to-expand:not(.expanded) {
5050
margin-right: auto;
5151
left: 0;
5252
right: 0;
53+
border: none;
54+
background-color: transparent;
55+
padding: 0;
56+
cursor: pointer;
57+
58+
&:focus-visible {
59+
outline: 2px solid currentColor;
60+
outline-offset: 2px;
61+
}
5362
}
5463
}
5564

5665
body:not(#en__pagebuilder) .click-to-expand.expanded {
57-
.click-to-expand-text-wrapper {
58-
outline: none;
66+
.click-to-expand-cta {
67+
display: none;
5968
}
60-
}
69+
}

0 commit comments

Comments
 (0)