woocommerce/plugins/woocommerce-blocks/assets/js/base/components/drawer/utils/aria-helper.ts

75 lines
2.0 KiB
TypeScript

/**
* Copied from https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/modal/aria-helper.ts
*/
const LIVE_REGION_ARIA_ROLES = new Set( [
'alert',
'status',
'log',
'marquee',
'timer',
] );
let hiddenElements: Element[] = [],
isHidden = false;
/**
* Determines if the passed element should not be hidden from screen readers.
*
* @param {HTMLElement} element The element that should be checked.
*
* @return {boolean} Whether the element should not be hidden from screen-readers.
*/
export function elementShouldBeHidden( element: Element ) {
const role = element.getAttribute( 'role' );
return ! (
element.tagName === 'SCRIPT' ||
element.hasAttribute( 'aria-hidden' ) ||
element.hasAttribute( 'aria-live' ) ||
( role && LIVE_REGION_ARIA_ROLES.has( role ) )
);
}
/**
* Hides all elements in the body element from screen-readers except
* the provided element and elements that should not be hidden from
* screen-readers.
*
* The reason we do this is because `aria-modal="true"` currently is bugged
* in Safari, and support is spotty in other browsers overall. In the future
* we should consider removing these helper functions in favor of
* `aria-modal="true"`.
*
* @param {HTMLDivElement} unhiddenElement The element that should not be hidden.
*/
export function hideApp( unhiddenElement?: HTMLDivElement ) {
if ( isHidden ) {
return;
}
const elements = Array.from( document.body.children );
elements.forEach( ( element ) => {
if ( element === unhiddenElement ) {
return;
}
if ( elementShouldBeHidden( element ) ) {
element.setAttribute( 'aria-hidden', 'true' );
hiddenElements.push( element );
}
} );
isHidden = true;
}
/**
* Makes all elements in the body that have been hidden by `hideApp`
* visible again to screen-readers.
*/
export function showApp() {
if ( ! isHidden ) {
return;
}
hiddenElements.forEach( ( element ) => {
element.removeAttribute( 'aria-hidden' );
} );
hiddenElements = [];
isHidden = false;
}