Archived topic
Accordion: Keyboard Navigation Issue. Open the Item with Hash in URL.
1 reply · Started by Rafał on March 20, 2023
Hi there,
Refers to GB 1.7.3 & GB Pro 1.5.2
My scenario: Using accordions for FAQ pages or as expanding "Read More" boxes with some rich content (with links, for example).
ACCORDION TITLE TYPE: Container
Accordion Title block has an unique HTML ANCHOR, and a link to itself (LINK TYPE: Wrapper)
or
ACCORDION TITLE TYPE: Button
Accordion Title > Advanced > Button Type: Link
1st:
I'd like to expand at once the Accordion Content which Accordion Title is pointed in the URL's hash, e.g. //example.com/faq/#how-to-survive
2nd:
When using keyboard navigation (tabbing), I'm getting lost with focus indicator inside hidden Accordion Contents, while they have any active (focusable) elements (like links, buttons, form elements)
I've written additional JavaScript to solve these accessibility problems.
And it does the job for me :)
document.addEventListener('DOMContentLoaded', () => {
const initialHash = window.location.hash.substr(1);
const accordionHeaders = document.querySelectorAll('.gb-accordion__toggle');
const focusables = '.gb-accordion__content a[href], .gb-accordion__content area[href], .gb-accordion__content button:not([disabled]), .gb-accordion__content input:not([disabled]), .gb-accordion__content select:not([disabled]), .gb-accordion__content textarea:not([disabled]), .gb-accordion__content iframe';
accordionHeaders.forEach((element) => {
element.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '-1'));
if (element.getAttribute('id') == initialHash) {
element.focus();
element.setAttribute('aria-expanded', true);
element.classList.add('gb-block-is-current');
element.parentElement.classList.add('gb-accordion__item-open');
element.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '0'));
}
element.addEventListener('keyup', (event) => {
accordionHeaders.forEach((el) => {
if (!el.parentNode.classList.contains('gb-accordion__item-open')) {
el.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '-1'));
}
});
if (event.keyCode == 32 || event.keyCode == 13) { // Space or Enter
if (element.parentNode.classList.contains('gb-accordion__item-open')) {
window.location.hash = '#' + event.currentTarget.getAttribute('id');
element.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '0'));
}
}
});
element.addEventListener('click', () => {
setTimeout(() => {
accordionHeaders.forEach((el) => {
if (!el.parentNode.classList.contains('gb-accordion__item-open')) {
el.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '-1'));
}
});
if (element.parentNode.classList.contains('gb-accordion__item-open')) {
element.parentNode.querySelectorAll(focusables).forEach((el) => el.setAttribute('tabIndex', '0'));
}
}, 200);
});
});
});
Do you see weak points of the JS above? Could you solve it more clever?
Or, possibly you may take those issues into account for future improvement of Accordion Block?
Hi Rafal,
The Accordion is a GB Pro feature so we cannot support it in this forum here.
Can you open a support ticket in GB's pro support system?
https://generateblocks.com/support/
Thanks!