-
Notifications
You must be signed in to change notification settings - Fork 137
Description
Description of bug or feature request
Accessibility testing frameworks currently have no way to query the ARIA semantics applied through ElementInternals within custom elements. This results in false positives and undetected issues across a growing ecosystem of web components that use ElementInternals to set accessibility roles and properties. Automated accessibility testing is typically performed by JavaScript libraries (e.g., axe-core) that run directly in the page context or in CI systems, and therefore must be able to query all author-provided accessibility information via standard DOM APIs.
This limitation has been raised in several issues, including aria#2656, aria#2655, and whatwg#11040. Proposals to address this at the ElementInternals level (e.g., relaxing encapsulation) have been discussed, but were met with valid concerns around encapsulation and design.
The goal of this issue is to gather thoughts from the ARIA WG about the feasibility of a proposed solution, and/or brainstorm about other solutions.
Proposal: Introduce a new get-only API surface (tentatively named implicitAria) to expose browser-default (or author-modified browser-default) accessibility semantics for DOM elements, including those defined via ElementInternals. Unlike standard ARIA reflection (which exposes explicitly set aria-* attributes), implicitAria would expose the implicit or default semantics the browser applies. This would be ideal for accessibility testing libraries such as axe-core.
Here are examples to demonstrate the idea:
- Native with no explicit role
<button id="b1">Save</button>
<script>
const b1 = document.getElementById('b1');
// ARIA reflection (explicit only): no role attribute present
console.log(b1.role); // undefined
// Proposed implicit semantics:
console.log(b1.implicitAria.role); // "button" (from native semantics)
</script>
- Custom element that sets role via ElementInternals
<script>
class CustomButton extends HTMLElement {
constructor() {
super();
this._internals = this.attachInternals();
this._internals.role = 'button'; // author-provided implicit role
}
}
customElements.define('custom-button', CustomButton);
</script>
<custom-button id="b2"></custom-button>
<script>
const b2 = document.getElementById('b2');
// No explicit role attribute on the host:
console.log(b2.role); // undefined
// Proposed implicit semantics reflect ElementInternals:
console.log(b2.implicitAria.role); // "button" (from ElementInternals)
</script>
- Native with an explicit role
<button id="b3" role="checkbox">Toggle</button>
<script>
const b3 = document.getElementById('b3');
// ARIA reflection exposes exactly what the author set:
console.log(b3.role); // "checkbox"
// Proposed implicit semantics still show the native default:
console.log(b3.implicitAria.role); // "button"
</script>
This solution doesn't require the browser to build the accessibility tree, it works similarly to how ARIA reflections work but for default values. I believe it stays clear from the privacy and performance issues we once discussed around AOM and the AccessibleNode proposal. It wouldn't leak the accessibility needs of a specific user, and is reasonably scoped. We could use a get-only version of the ARIAMixin interface to expose the full set of aria attributes.
Will this require a change to CORE-AAM?
No.
Will this require a change to the ARIA authoring guide?
It shouldn't.