Table of Contents
- Phase 1
- Phase 2
- Phase 3
- Open questions
- Which ARIA relationship properties should be exposed as element references and under what names?
- How do we attach a virtual
AccessibleNodesubtree? - How does the virtual
AccessibleNodesubtree interact with the DOM tree? - Can virtual
AccessibleNodes be used in relationships with DOM elements? - Do we need a new API for collection types?
- Why does a
ShadowRootneed anaccessibleNodefor default semantics?
Setting ARIA properties on non-Custom Elements should just be ARIA. We should just make ARIA reflect in IDL.
el.ariaLabel = "banana";
el.ariaHidden = true; // auto-converts to "true" since this is a string attribute
el.role = "button"; // no validation, this is just a string
el.ariaLabelledby = "an-idref"; // not an element ref hereRather than add these directly to the Element interface, we propose this be implemented as a mixin interface:
interface mixin ARIAProperties {
[Reflect] [Unscopable] attribute DOMString? ariaActiveDescendant;
[Unscopable] attribute Element? ariaActiveDescendantElement;
[Reflect] [Unscopable] attribute boolean? ariaAtomic;
[Reflect] [Unscopable] attribute DOMString? ariaAutocomplete;
[Reflect] [Unscopable] attribute boolean? ariaBusy;
[Reflect] [Unscopable] attribute DOMString? ariaChecked;
[Reflect] [Unscopable] attribute short? ariaColCount;
// ...
[Reflect] [Unscopable] attribute DOMString? role;
}
Element includes ARIAProperties;Other DOM relationships like htmlFor suffer the same issues as the ARIA relationships regarding ergonomics and Shadow DOM.
We propose that we have a common pattern for all non-tree relationships (including htmlFor):
el.htmlFor = 'id-for-my-input';
el.htmlForElement = myInput; // overrides htmlFor
myCustomInput.ariaActiveDescendant = 'id-for-my-label';
myCustomInput.ariaActiveDescendantElement = myLabel; // overrides ariaActiveDescendant
myCustomInput.ariaOwns = 'id-for-autocomplete-1';
myCustomInput.ariaOwnsElements = [autocomplete1, autocomplete2]; // overrides ariaOwnsAll the ARIA relationship element properties would also be a part of the ARIAProperties mixin.
When using a property which may be set either via an IDREF or IDREF list string or via an element reference or list of elements, the element reference should take precedence.
For example, if both ariaLabelledBy and ariaLabelledByElements
were set to refer to different non-null values,
then ariaLabelledBy should be ignored in favour of ariaLabelledByElements.
If ariaLabelledByElements was explicitly set to null, or an empty list,
or never set, then ariaLabelledBy should be used.
Instead of attaching event listeners to the AccessibleNode object, we make the "accessible" events available to Elements.
el.addEventListener('accessibleincrement', function() {
el.value += 1;
});
el.addEventListener('accessibledecrement', function() {
el.value -= 1;
});We would need a way to prompt in an appropriate and timely manner for user permission to listen for assistive technology events.
// An AccessibleNode represents a virtual accessible node.
interface AccessibleNode {};
AccessibleNode includes ARIAProperties;
interface AccessibleRoot : AccessibleNode {}; // needed?- Calling
attachAccessibleRoot()causes anAccessibleRootto be associated with aNode.- The
AccessibleRootforms the root of a virtual accessibility tree. - The Node's DOM children are implicitly ignored for accessibility once an
AccessibleRootis attached - there is no mixing of DOM children and virtual accessible nodes.
- The
- Like
ShadowRoot, an element may only have one associatedAccessibleRoot. - Only
AccessibleNodes may haveAccessibleNodesas children, andAccessibleNodes may only haveAccessibleNodes as children.
// Implementing a canvas-based spreadsheet's semantics
canvas.attachAccessibleRoot();
let table = canvas.accessibleRoot.appendChild(new AccessibleNode());
table.role = 'table';
table.ariaColCount = 10;
table.ariaRowcount = 100;
let headerRow = table.appendChild(new AccessibleNode());
headerRow.role = 'row';
headerRow.ariaRowindex = 0;
// etc. etc.We would add an accessibleNode property on to the ShadowRoot interface,
which would allow setting default semantics for the host node.
class HowToCheckbox extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
// The default role of the host node should be 'checkbox'.
this.shadowRoot.accessibleNode = 'checkbox';
}
// ...
}
window.customElements.define('howto-checkbox', HowToCheckbox);<!-- ARIA role overrides AccessibleRoot role -->
<!-- If an author removes the ARIA role, the computed role reverts to "checkbox". -->
<howto-checkbox role="radio"></howto-checkbox>- Initial idea: begin only with
aria-labelledby,aria-describedbyandaria-activedescendant, and then assess.
- A "strawman" API is proposed above, but are there other proposals?
- Can DOM Elements be mixed in to the virtual subtree, like slots in a Shadow tree?
- Simplest proposal: no, once a virtual subtree is attached, it overrides all DOM children of the host Element.
- To be consistent with not mixing the two trees, perhaps not?
- If
AccessibleNodeis primarily intended for building virtual accessibility trees, are we building a kind of virtual accessibility tree on theShadowRoot? IsAccessibleNodea node or a bag of properties in this case? - Alternative: define accessible properties directly on
ShadowRootusing the ARIA vocabulary instead.
Note: this comment refers to an earlier revision
@ aria-* and @ role reflected in IDL on Element is fine with me, but that should just be part of an ARIA or DOM spec update.
However, I'm not convinced that reflected ARIA attrs should replace the existing Phase 1's Element.accessibleNode. Also, I'd prefer it not use the aria-prefixed property on accessibleNode because a) It seems to limit AOM to existing ARIA attrs, and b) Many of these pseudo-reflected relationships may be confusing to authors.
The code samples above are not reflected IDL, but a unique hybrid of reflection, inference, and validation. For example, I find this very confusing (quoting from above):
Doesn't this preclude the intended use of AOM Phase 1 to support relationships without IDREF, including across shadow root boundaries?
ARIA was, to some degree, a declarative workaround for the lack of a scripted interface into the browser's accessibility tree. I expect that trying to re-map declarative ARIA into a JavaScript API will be full of challenges. String-only reflection in IDL is fine (I would support this in the ARIA spec), but I would not want to design a JavaScript API that copies ARIA verbatim.