Disclosure: This issue is just to brainstorm on the proposed linking mechanism and maybe open other avenues.
A very common use-case is to have custom elements that should be described by sibling elements,
<template>
<span id="global-one">description for x-foo element</span>
<fancy-input aria-describedby="global-one">
</fancy-input>
</template>
Assuming that fancy-input element contains some internal focusable elements, and itself is relying on delegate focus to facilitate the user interaction, e.g.:
<template>
<span id="global-one">description for x-foo element</span>
<fancy-input aria-describedby="global-one">
#shadow-dom (mode=closed, delegateFocus=true)
<label id="local-one">...</label>
<input aria-describedby="local-one" />
</fancy-input>
</template>
It is still impossible to connect those elements from outside (#global-one) and from within (input) without opening some sort of side-channel on fancy-input element. I see two options to achieve this:
- expose a method on
<fancy-input> custom element that when called with one argument (an element), it sets that element into the internal input's ariaDescribedByElements collection. (with the corresponding guards and deduping).
- expose a method on
<fancy-input> custom element that when invoked without arguments return a reference to the internal input element.
Either way, it is going to be bad, error prompt or leaky, this is one of those situations when you have to take a poison.
Another option is to observe the aria attributes on the host, walk from the host all the way to the nearest root, and query for the ID from there to try to do some auto-wiring via imperative APIs. This should work fine, but the problem is that since you're in control of the situation as the author of the component, you will have to observe mutations to rewire when needed. This makes the situation very error prompt, while the option 1 and 2 outsource that responsibility to the consumer of the custom element.
Proposal
When discussing this with the team, we were wondering whether or not the delegate focus on the shadow root could be sufficient indication for some sort of compounding mechanism for some of these aria-* attributes that reference IDs. In the example above, you can see that from the consumer perspective (the owner of the template), you can do the regular connecting between the two elements via IDs, they are in the same shadow after all.
But from the component's author perspective, just signaling that the root should receive the focus (via delegateFocus configuration), could be used to build the right tree under the hood that connects the input with both elements (#global-one and #local-one) without the user having to do so manually.
Pros:
- declarative works again
- very intuitive (you just don't need to know how the fancy-input works)
Cons:
- how to opt-out from this behavior? is it possible to opt-out?
Disclosure: This issue is just to brainstorm on the proposed linking mechanism and maybe open other avenues.
A very common use-case is to have custom elements that should be described by sibling elements,
Assuming that
fancy-inputelement contains some internal focusable elements, and itself is relying on delegate focus to facilitate the user interaction, e.g.:It is still impossible to connect those elements from outside (
#global-one) and from within (input) without opening some sort of side-channel onfancy-inputelement. I see two options to achieve this:<fancy-input>custom element that when called with one argument (an element), it sets that element into the internal input'sariaDescribedByElementscollection. (with the corresponding guards and deduping).<fancy-input>custom element that when invoked without arguments return a reference to the internal input element.Either way, it is going to be bad, error prompt or leaky, this is one of those situations when you have to take a poison.
Another option is to observe the aria attributes on the host, walk from the host all the way to the nearest root, and query for the ID from there to try to do some auto-wiring via imperative APIs. This should work fine, but the problem is that since you're in control of the situation as the author of the component, you will have to observe mutations to rewire when needed. This makes the situation very error prompt, while the option 1 and 2 outsource that responsibility to the consumer of the custom element.
Proposal
When discussing this with the team, we were wondering whether or not the delegate focus on the shadow root could be sufficient indication for some sort of compounding mechanism for some of these
aria-*attributes that reference IDs. In the example above, you can see that from the consumer perspective (the owner of the template), you can do the regular connecting between the two elements via IDs, they are in the same shadow after all.But from the component's author perspective, just signaling that the root should receive the focus (via delegateFocus configuration), could be used to build the right tree under the hood that connects the input with both elements (
#global-oneand#local-one) without the user having to do so manually.Pros:
Cons: