1. Introduction
Content on the web be accessible is critically important. Maintaining accessibility within web components is challenging as the shadow root encapsulation prevents references between elements in different roots. These references are fundamental to enable assistive technologies within web applications.
Today, a web application can be composed by many web components that are connected through different relationships. ARIA is the appropriate standard to describe those relationships. Unfortunately, it’s not possible to natively connect ARIA attributes from elements belonging to different DOM trees belonging to the main page and one or many web components. Because of that, some complex and not fully successful workarounds need to be applied.
-
Observing and moving ARIA-related attributes across elements (for role, etc.).
-
Using non-standard attributes for ARIA features, in order to apply them to elements in a shadow root.
-
Requiring usage of custom elements to wrap/slot elements so that ARIA attributes can be placed directly on them. This gets very complicated as the number of slotted inputs and levels of shadow root nesting increase.
-
Duplicating nodes across shadow root boundaries.
-
Abandoning Shadow DOM.
1.1. This proposal
This proposal introduces a delegation API to allow for ARIA attributes and properties set on a Web Component to be forwarded to elements inside of its shadowroot.
This mechanism will allow users to apply standard best practices for ARIA and resolve a large margin of accessibility use cases for applications of native Web components and native Shadow DOM. This API is most suited for one-to-one delegation, but should also work for one-to-many scenarios. There is no mechanism for directly relating two elements in different shadowroots together, but this will still be possible manually with the element reflection API.
The proposed extension adds a new `delegates*` (e.g.: `delegatesAriaLabel`, `delegatesAriaDescribedBy`) options to the `.attachShadow` method similarly to the `delegatesFocus`, while introducing a new content attribute `auto*` (e.g.: `autoarialabel`, `autoariadescribedby`) to be used in the shadowroot inner elements. This has an advantage that it works with Declarative Shadow DOM as well, and it is consistent with `delegatesFocus`. Even though, it requires another set of html attributes in the declarative shadow root template. The declarative form works better with common developer paradigm where you may not necessarily have access to a DOM node right where you’re creating / declaring it.
The attributes names such as `shadowrootdelegates*` are very long and some consideration for shorter names by removing the `shadowroot` prefix can be discussed as long the discussion is sync’ed with the stakeholders of the respective Declarative Shadow DOM proposal.
2. IDL Interface
Conforming user agents MUST implement the following IDL interface.
2.1. Interface Mixin AutoARIAMixin
interface mixin {
AutoARIAMixin attribute DOMString ?;
autoAriaAtomic attribute DOMString ?;
autoAriaAutoComplete attribute DOMString ?;
autoAriaBusy attribute DOMString ?;
autoAriaChecked attribute DOMString ?;
autoAriaColCount attribute DOMString ?;
autoAriaColIndex attribute DOMString ?;
autoAriaColIndexText attribute DOMString ?;
autoAriaColSpan attribute DOMString ?;
autoAriaCurrent attribute DOMString ?;
autoAriaDescription attribute DOMString ?;
autoAriaDisabled attribute DOMString ?;
autoAriaExpanded attribute DOMString ?;
autoAriaHasPopup attribute DOMString ?;
autoAriaHidden attribute DOMString ?;
autoAriaInvalid attribute DOMString ?;
autoAriaKeyShortcuts attribute DOMString ?;
autoAriaLabel attribute DOMString ?;
autoAriaLevel attribute DOMString ?;
autoAriaLive attribute DOMString ?;
autoAriaModal attribute DOMString ?;
autoAriaMultiLine attribute DOMString ?;
autoAriaMultiSelectable attribute DOMString ?;
autoAriaOrientation attribute DOMString ?;
autoAriaPlaceholder attribute DOMString ?;
autoAriaPosInSet attribute DOMString ?;
autoAriaPressed attribute DOMString ?;
autoAriaReadOnly attribute DOMString ?;
autoAriaRequired attribute DOMString ?;
autoAriaRoleDescription attribute DOMString ?;
autoAriaRowCount attribute DOMString ?;
autoAriaRowIndex attribute DOMString ?;
autoAriaRowIndexText attribute DOMString ?;
autoAriaRowSpan attribute DOMString ?;
autoAriaSelected attribute DOMString ?;
autoAriaSetSize attribute DOMString ?;
autoAriaSort attribute DOMString ?;
autoAriaValueMax attribute DOMString ?;
autoAriaValueMin attribute DOMString ?;
autoAriaValueNow attribute DOMString ?; };
autoAriaValueText
Interfaces that include `AutoARIAMixin` must provide the following algorithms:
-
`AutoARIAMixin` getter steps, which take the host interface instance, IDL attribute name, and content attribute name, and must return a string value; and
-
`AutoARIAMixin` setter steps, which take the host interface instance, IDL attribute name, content attribute name, and string value, and must return nothing.
For every IDL attribute idlAttribute defined in `AutoARIAMixin`, on getting, it must perform the following steps:
-
Let contentAttribute be the AutoARIA content attribute determined by looking up idlAttribute in the AutoARIA Attribute Correspondence table.
-
Return the result of running the `AutoARIAMixin` getter steps, given this, idlAttribute, and contentAttribute.
Similarly, on setting, it must perform the following steps:
-
Let contentAttribute be the AutoARIA content attribute determined by looking up idlAttribute in the AutoARIA Attribute Correspondence table.
-
Run the `AutoARIAMixin` setter steps, given this, idlAttribute, contentAttribute, and the given value.
2.2. AutoARIA Attribute Correspondence
The following table provides a correspondence between IDL attribute names and content attribute names, for use by `AutoARIAMixin`.
2.3. `AutoARIAMixin` Mixed in to `Element`
User agents MUST include `AutoARIAMixin` on `Element`:
Element includes AutoARIAMixin ;
For `Element`:
-
The `AutoARIAMixin` getter steps given element, idlAttribute, and contentAttribute are to return the result of the getter algorithm for idlAttribute reflecting<contentAttribute on element.
-
The `AutoARIAMixin` setter steps given element, idlAttribute, contentAttribute, and value are to perform the setter algorithm for idlAttribute reflecting contentAttribute on element, given value.
Note: In practice, this means that, e.g., the `autoAriaAtomic` IDL on `Element` reflects the `autoariaatomic` content attribute;
2.4. Interface Mixin ShadowRootMixin
interface mixin {
ShadowRootMixin attribute DOMString ?;
delegatesAriaAtomic attribute DOMString ?;
delegatesAriaAutoComplete attribute DOMString ?;
delegatesAriaBusy attribute DOMString ?;
delegatesAriaChecked attribute DOMString ?;
delegatesAriaColCount attribute DOMString ?;
delegatesAriaColIndex attribute DOMString ?;
delegatesAriaColIndexText attribute DOMString ?;
delegatesAriaColSpan attribute DOMString ?;
delegatesAriaCurrent attribute DOMString ?;
delegatesAriaDescription attribute DOMString ?;
delegatesAriaDisabled attribute DOMString ?;
delegatesAriaExpanded attribute DOMString ?;
delegatesAriaHasPopup attribute DOMString ?;
delegatesAriaHidden attribute DOMString ?;
delegatesAriaInvalid attribute DOMString ?;
delegatesAriaKeyShortcuts attribute DOMString ?;
delegatesAriaLabel attribute DOMString ?;
delegatesAriaLevel attribute DOMString ?;
delegatesAriaLive attribute DOMString ?;
delegatesAriaModal attribute DOMString ?;
delegatesAriaMultiLine attribute DOMString ?;
delegatesAriaMultiSelectable attribute DOMString ?;
delegatesAriaOrientation attribute DOMString ?;
delegatesAriaPlaceholder attribute DOMString ?;
delegatesAriaPosInSet attribute DOMString ?;
delegatesAriaPressed attribute DOMString ?;
delegatesAriaReadOnly attribute DOMString ?;
delegatesAriaRequired attribute DOMString ?;
delegatesAriaRoleDescription attribute DOMString ?;
delegatesAriaRowCount attribute DOMString ?;
delegatesAriaRowIndex attribute DOMString ?;
delegatesAriaRowIndexText attribute DOMString ?;
delegatesAriaRowSpan attribute DOMString ?;
delegatesAriaSelected attribute DOMString ?;
delegatesAriaSetSize attribute DOMString ?;
delegatesAriaSort attribute DOMString ?;
delegatesAriaValueMax attribute DOMString ?;
delegatesAriaValueMin attribute DOMString ?;
delegatesAriaValueNow attribute DOMString ?; };
delegatesAriaValueText
Interfaces that include `ShadowRootMixin` must provide the following algorithms:
-
`ShadowRootMixin` getter steps, which take the host interface instance, IDL attribute name, and content attribute name, and must return a string value; and
-
`ShadowRootMixin` setter steps, which take the host interface instance, IDL attribute name, content attribute name, and string value, and must return nothing.
For every IDL attribute idlAttribute defined in `ShadowRootMixin`, on getting, it must perform the following steps:
-
Let contentAttribute be the AutoARIA content attribute determined by looking up idlAttribute in the AutoARIA Attribute Correspondence table.
-
Return the result of running the `ShadowRootMixin` getter steps, given this, idlAttribute, and contentAttribute.
Similarly, on setting, it must perform the following steps:
-
Let contentAttribute be the AutoARIA content attribute determined by looking up idlAttribute in the AutoARIA Attribute Correspondence table.
-
Run the `ShadowRootMixin` setter steps, given this, idlAttribute, contentAttribute, and the given value.
2.5. ShadowRoot Attribute Correspondence
The following table provides a correspondence between IDL attribute names and content attribute names, for use by `ShadowRootMixin`.
2.6. `ShadowRootMixin` Mixed in to `ShadowRoot`
User agents MUST include `ShadowRootMixin` on `ShadowRoot`:
ShadowRoot includes ShadowRootMixin ;
For `ShadowRoot`:
-
The `ShadowRootMixin` getter steps given element, idlAttribute, and contentAttribute are to return the result of the getter algorithm for idlAttribute reflecting<contentAttribute on element.
-
The `ShadowRootMixin` setter steps given element, idlAttribute, contentAttribute, and value are to perform the setter algorithm for idlAttribute reflecting contentAttribute on element, given value.
Note: In practice, this means that, e.g., the `delegatesAriaAtomic` IDL on `ShadowRoot` reflects the `delegatesariaatomic` content attribute; etc
2.7. ShadowRootExtInit
[Exposed =Window ]dictionary :
ShadowRootExtInit ShadowRootInit {boolean =
delegatesAriaDescribedBy false ;boolean =
delegatesAriaAtomic false ;boolean =
delegatesAriaAutoComplete false ;boolean =
delegatesAriaBusy false ;boolean =
delegatesAriaChecked false ;boolean =
delegatesAriaColCount false ;boolean =
delegatesAriaColIndex false ;boolean =
delegatesAriaColIndexText false ;boolean =
delegatesAriaColSpan false ;boolean =
delegatesAriaCurrent false ;boolean =
delegatesAriaDescription false ;boolean =
delegatesAriaDisabled false ;boolean =
delegatesAriaExpanded false ;boolean =
delegatesAriaHasPopup false ;boolean =
delegatesAriaHidden false ;boolean =
delegatesAriaInvalid false ;boolean =
delegatesAriaKeyShortcuts false ;boolean =
delegatesAriaLabel false ;boolean =
delegatesAriaLevel false ;boolean =
delegatesAriaLive false ;boolean =
delegatesAriaModal false ;boolean =
delegatesAriaMultiLine false ;boolean =
delegatesAriaMultiSelectable false ;boolean =
delegatesAriaOrientation false ;boolean =
delegatesAriaPlaceholder false ;boolean =
delegatesAriaPosInSet false ;boolean =
delegatesAriaPressed false ;boolean =
delegatesAriaReadOnly false ;boolean =
delegatesAriaRequired false ;boolean =
delegatesAriaRoleDescription false ;boolean =
delegatesAriaRowCount false ;boolean =
delegatesAriaRowIndex false ;boolean =
delegatesAriaRowIndexText false ;boolean =
delegatesAriaRowSpan false ;boolean =
delegatesAriaSelected false ;boolean =
delegatesAriaSetSize false ;boolean =
delegatesAriaSort false ;boolean =
delegatesAriaValueMax false ;boolean =
delegatesAriaValueMin false ;boolean =
delegatesAriaValueNow false ;boolean =
delegatesAriaValueText false ; };
2.8. attachShadow Signature
User agents MUST update the attachShadow method signature in the Element
with the ShadowRootExtInit option, as the following:
ShadowRoot attachShadow(ShadowRootExtInit init);
2.9. attachShadow Extension
The `attachShadow` method steps have their last 2 steps with:
-
Set each attribute in the § 2.9.1 Delegates Aria Attribute Correspondence {#delegates-correspondence} table into shadow to the corresponding init[delegates attribute].
-
Set this’s shadow root to shadow.
-
Return shadow.
2.9.1. Delegates Aria Attribute Correspondence {#delegates-correspondence}
Attribute | Delegates |
---|---|
delegates ariaDescribedBy | delegatesAriaDescribedBy |
delegates ariaAtomic | delegatesAriaAtomic |
delegates ariaAutoComplete | delegatesAriaAutoComplete |
delegates ariaBusy | delegatesAriaBusy |
delegates ariaChecked | delegatesAriaChecked |
delegates ariaColCount | delegatesAriaColCount |
delegates ariaColIndex | delegatesAriaColIndex |
delegates ariaColIndexText | delegatesAriaColIndexText |
delegates ariaColSpan | delegatesAriaColSpan |
delegates ariaCurrent | delegatesAriaCurrent |
delegates ariaDescription | delegatesAriaDescription |
delegates ariaDisabled | delegatesAriaDisabled |
delegates ariaExpanded | delegatesAriaExpanded |
delegates ariaHasPopup | delegatesAriaHasPopup |
delegates ariaHidden | delegatesAriaHidden |
delegates ariaInvalid | delegatesAriaInvalid |
delegates ariaKeyShortcuts | delegatesAriaKeyShortcuts |
delegates ariaLabel | delegatesAriaLabel |
delegates ariaLevel | delegatesAriaLevel |
delegates ariaLive | delegatesAriaLive |
delegates ariaModal | delegatesAriaModal |
delegates ariaMultiLine | delegatesAriaMultiLine |
delegates ariaMultiSelectable | delegatesAriaMultiSelectable |
delegates ariaOrientation | delegatesAriaOrientation |
delegates ariaPlaceholder | delegatesAriaPlaceholder |
delegates ariaPosInSet | delegatesAriaPosInSet |
delegates ariaPressed | delegatesAriaPressed |
delegates ariaReadOnly | delegatesAriaReadOnly |
delegates ariaRequired | delegatesAriaRequired |
delegates ariaRoleDescription | delegatesAriaRoleDescription |
delegates ariaRowCount | delegatesAriaRowCount |
delegates ariaRowIndex | delegatesAriaRowIndex |
delegates ariaRowIndexText | delegatesAriaRowIndexText |
delegates ariaRowSpan | delegatesAriaRowSpan |
delegates ariaSelected | delegatesAriaSelected |
delegates ariaSetSize | delegatesAriaSetSize |
delegates ariaSort | delegatesAriaSort |
delegates ariaValueMax | delegatesAriaValueMax |
delegates ariaValueMin | delegatesAriaValueMin |
delegates ariaValueNow | delegatesAriaValueNow |
delegates ariaValueText | delegatesAriaValueText |