Skip to content

Instantly share code, notes, and snippets.

@TerribleDev
Last active June 23, 2022 15:49
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TerribleDev/51049146e00b36b0d8643f5e09d21ea8 to your computer and use it in GitHub Desktop.
Save TerribleDev/51049146e00b36b0d8643f5e09d21ea8 to your computer and use it in GitHub Desktop.
Use axe core to put ugly borders around elements that are not accessible
import axe from 'axe-core';
function debounce(fn, wait) {
let timeout = null;
return function (...args) {
const next = () => fn.apply(this, args);
clearTimeout(timeout);
timeout = setTimeout(next, wait);
};
}
/**
* Not all elements support shadow dom (such as image) ascent the parent tree until the closest element is found
*
* @param {HTMLElement} node
* @returns
*/
function resolveClosestShadowRoot(node) {
if (!node) {
return null;
}
if (node.attachShadow) {
return node;
}
return resolveClosestShadowRoot(node.parentElement);
}
/**
* Places a red boarder on an Element
*
* @param {HTMLElement} node
*/
function styleNode(node) {
// does the browser support shadow dom?
if (!document.head.attachShadow) {
return;
}
// has the node been GC'd
if (!node) {
return;
}
try {
const resolvedNodeToShadow = resolveClosestShadowRoot(node);
// if we can't resolve a node to shadow, or the node to shadow has a shadow dom already, skip
if (!resolvedNodeToShadow || resolvedNodeToShadow.shadowRoot) {
return;
}
try {
const shadowRoot = resolvedNodeToShadow.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<style>:host { outline: red solid 1rem; }</style><slot></slot>';
} catch (e) {
styleNode(resolvedNodeToShadow.parentNode);
}
} catch (e) {}
}
function domChange() {
axe.run({
elementRef: true,
runOnly: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'],
}).then((results) => {
console.group('A11y Errors');
results?.violations?.forEach((violation) => {
console.error(violation);
// do we have the shadow dom feature? and do we visually allow a11y checker
if (document.head.attachShadow) {
violation.nodes.forEach((axeNode) => styleNode(axeNode.element));
}
});
if (results?.violations?.length > 0) {
console.error(
'Accessibility violations found.',
);
}
console.groupEnd('A11y Errors');
});
}
const debounceObserve = debounce(domChange, 1000);
const observer = new MutationObserver(debounceObserve);
observer.observe(document.querySelector('body'), { childList: true, subtree: true });
document.addEventListener('DOMContentLoaded', debounceObserve);
console.log('initalizing a11y detector');
setTimeout(debounceObserve, 0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment