-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reference Target #961
Comments
This isn't a TAG opinion, but I wanted to point out that there's a known gap across the whole platform in the ability of IDREF attributes to refer to what authors want: w3ctag/gaps#2. I know that this particular gap in ARIA references has lingered for a very long time, and I don't want to delay getting it fixed, but it's also important to keep looking for a unified strategy to deal with all of these relation types. |
We discussed in the TAG meetings this week, and while we haven't reviewed Phase 2 yet, we're in favor of you moving ahead with solving the piece of this (Phase 1) that you have general agreement on. We'll continue reviewing Phase 2 in future weeks. |
Have you considered reversing the relationship of the shadow root to the target node? For example, rather than having the developer set the I'm thinking of the developer ergonomics, for instance if I'm building a select-type control, in the current model I have to set some attribute (probably a class) on the currently selected node to indicate its selected state and trigger style changes, and then I have to also add an id and set the |
That sounds like this considered alternative: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/reference-target-explainer.md#designate-target-elements-using-attributes-instead-of-idref, which @Westbrook proposed in more depth in https://github.com/Westbrook/cross-root-aria-reflection/blob/main/cross-root-aria-reflection.md. IMO the developer ergonomics are similar in the use case you mentioned. They way I would handle the <input role="combobox" aria-activedescendant="fancy-listbox"/>
<fancy-listbox id="fancy-listbox" >
<template shadowrootmode="open" shadowrootreferencetarget="active">
<style>
#active { /* styles for the active element go here */ }
</style>
<option>One</option>
<option id="active">Two</option>
<option>Three</option>
</template>
</fancy-listbox> If the user selects another option, the only thing the dev needs to change is to clear the ID from option Two and add it to the new option. This is the same amount of state that would need to be changed if reference target was set using a property on the targeted element. Semantically, it also feels to me that the choice of whether or not to delegate a given attribute is something that should be set on the shadow root, akin to delegatesfocus, which maybe is why @Westbrook's proposal used both a property on the shadow root and a property on the targeted element. |
When discussing this at length with the AOM Working Group, the WCCG, and implementors, a primary shortcoming for an attribute marker being applied to an element within the shadow DOM is that in order for the API to scale over time to support mapping more than one attribute to more than one element you needed to inform the shadow root that it would be delegating a value and to which element the value would be delegated. If the delegation/reflection APIs were to stop at a one to one pass through, so no support for something like |
I'm not sure I see a practical difference between the two contexts that you're referencing @LeaVerou. While the code above is a very reduced reproduction, the workflow I outlined applies to the work I've seen or been a part of across a number of roles I've worked in. Whether building Spectrum Web Components where we commonly worked to translate examples like those found in ARIA APG into abstract reusable/customizable element or building interactive virtual classrooms, digital asset management or creativity tools that rely on larger custom element architectures, I see this approach being valuable in the way that it manages ID references much like they would be used without shadow DOM. But, maybe I'm misunderstanding the context you're outlining. Would you be able to share some code outlining how that context would be different? Something that helped clarify how this context would benefit from managing ID references via this net new API surface? |
i don’t really have a strong preference for either api as long as something moves forward that helps. but i do think the perf aspect of the two approaches is important to consider. if the map of els needing ids to shadow dom ids is established on the shadow root/host itself, then the browser doesn’t have to fully parse the shadow root template in order to finish calculating the references. the browser would have the complete map upfront as soon as the shadow root is constructed. likewise, the mapping being on the root doesn’t change the performance of calculating the map as the size of the shadow dom grows. the map will always be in a single spot which may mean that browsers can optimize for it since it’ll be known and predictable. i do think that the attrs establishing IDREF mappings being on the SD child elements themselves is a more flexible api, but i would be interested in how big the perf tradeoff is for having to parse the whole SD template in order to assign refs. possibly the perf impact would be mitigated by assigning each IDREF when each attr is encountered, and overwriting the assignment if a conflicting attr is encountered later on. but then i’d worry about the impact of the assignment changing. if i were the kind of dev writing uber-optimized framework code i might balk at references changing mid-parse? |
@michaelwarren1106 This can be mitigated by simply using the first instance of the attribute (for references of the same scope). Even with ids the association can change — one can simply remove an element with that id and add a different one, or modify ids at runtime, so that doesn't seem different? |
Perhaps, but I'm not sure I know of anything else that changes ref like that during tree parsing? Implementers would be better to weigh in on the pros/cons of that approach, but I would suspect that changing the ref during the parse is wholly different than changing the ref as a result of manipulating the dom. And actually, I think that manipulating the dom is another perf lever where the "having to parse the whole dom in order for refs to settle out" is maybe not the best. What if the dom structure changes, but the ref map doesnt? If im moving elements around in the dom, but not changing their IDREF relationships to their But if the ref/mapping is set on the shadow root itself, then that frees up the dom to be changed without the IDREFs needing to also be recalculated. And vice-versa, the IDREFs could be changed (potentially, I havent seen any imperative feature that would do that) without being dependent on the dom structure. Having talked myself into it just now, it seems like disconnecting the actual DOM from the IDREF mapping metadata seems like a good thing to do even if its slightly worse DX? slightly worse DX for way better performance is a tradeoff many people would make I would think. |
One potential issue I can see with the non- For example, in the current proposal (omitting some details for brevity): <input role="combobox" aria-activedescendant="listbox">
<fancy-listbox id="listbox">
<template shadowrootmode="open" shadowrootreferencetargetmap="aria-activedescendant: one">
<div role="listbox">
<div id="one" role="option">one</div>
<div id="two" role="option">two</div>
</div>
</template>
</fancy-listbox> To update the active descendant from Whereas with the <input role="combobox" aria-activedescendant="listbox">
<fancy-listbox id="listbox">
<template shadowrootmode="open">
<div role="listbox">
<div role="option" referenceTargetForAttributes="aria-activedescendant">one</div>
<div role="option">two</div>
</div>
</template>
</fancy-listbox> Now the update would require 2 operations: 1) removing IMO this isn't a deal-breaker, but given that the first proposal is fewer operations and closer to the non-shadow DOM equivalent, the first would be my preference. (BTW this combobox likely requires |
Would the use of <label for="input">Label</label>
<my-input id="input">
<template shadowrootmode="open">
<input id="input" defaultReferenceTarget>
</template>
</my-input> To one that took multiple targets, as found here: <form id="example-form">
<input type="range" id="b" name="b" value="50" /> +
<input type="number" id="a" name="a" value="10" /> =
<output name="result" for="a b">60</output>
</form> I will admit, it is a bit contrived, but were this factored for reusability via the following, would "simply using the first instance of the attribute" be enough to make this work as expected? <form id="example-form">
<calc-el>
<template shadowrootmode="open">
<input type="range" id="b" referenceTargetForAttributes="for" value="50" /> +
<input type="number" id="a" referenceTargetForAttributes="for" value="10" /> =
</template>
</calc-el>
<output name="result" for="a b">60</output>
</form>
|
Addressing @LeaVerou's comment above:
For things like For example: <input aria-labelledby="b a">
<div id="a">two</div>
<div id="b">one</div> The accessible name of the @jyasskin said:
Changing the behavior of labelledby-describedby recursion within shadow roots seems like a recipe for confusion. There is some evidence that developers expect and depend on these properties not chaining. Rather than adding another element of complexity to labeledby/describedby by making them behave differently depending on context I'd prefer to just go with the version of ReferenceTarget that allows reordering these in the way that developers are already accustomed to, by ordering IDs in an attribute list. |
@Westbrook's example I think illustrates why this problem gets very hard for me to reason about from a general perspective when there's not a 1:1 mapping between the shadow host and the reference target. Even leaving aside the syntax, I would struggle to reason about what should happen in a case like this: <form>
<label for="sum">Equation</label>
<calc-el id="sum">
<template shadowrootmode="open">
<input type="range" referenceTargetForAttributes="for" value="50" /> +
<input type="number" referenceTargetForAttributes="for" value="10" /> =
</template>
</calc-el>
<output name="result" for="sum">60</output>
</form> So, I've tried to think about specific cases instead. There are three types of non-contrived cases for this type of API I am reasonably confident I can get my head around (thanks to the folks who have patiently explained the latter two to me across multiple occasions):
For (1), I think the current That said, I don't necessarily have any objection to having an attribute on the substitute element instead; I can't see any major practical downside of either design for this case, particularly if you can retrieve the reference target from the shadow root for debugging. For (2), we're arguably getting an upgrade on the status quo regardless of syntax, since the listbox no longer needs to coordinate with the Since For (3), I do wonder like @jyasskin whether this is the best approach at all. I understand that there is a general expectation around how And if we really can't come up with a case other than (2) for the reference map, I wonder likewise whether we could find a way to improve on this case in isolation. |
If we go with the current id-based syntax, I wonder what ergonomics improvements we could make:
|
Not sure what I prefer but trying to think it through, I think this captures most of the points mentioned but happy to correct or amend as needed.
|
Thanks for the summary @sorvell! I'd add to the disadvantages of the current approach that it makes it harder to solve the referencing problem in HTML. |
One option that has not been explored: using relative selectors. It both solves the ordering issue and alleviates the need for naming. People who want to use ids can still use ids by just doing |
Another issue we realized: Right now, the design for the whole feature is that an attribute specifies the defaults, and another one-off overrides on an attribute by attribute basis. If no default forwarding is specified, no forwarding happens (i.e. the reference resolves to the element itself). However, the pattern where everything gets delegated to a certain shadow DOM element but some attributes don't get forwarded at all is not supported at all with the id-based syntax. That is also something a selector-based syntax could address, as then Also, from conversations with folks, the initial reaction for phrase 1 is "yes, forwarding everything to the same element makes sense, all our use cases are like that", then I remind them about the non-a11y idrefs such as |
One issue with using selectors in place of IDs is that selectors don't come with the same constraints as IDs. In particular, almost anything about the element can affect whether it matches a selector, and many selectors can match any number of elements. This would be an issue for things like |
Thank you for your time earlier in the week. As per our discussion, we are happy to see your work on phase 1 progress. It will be great to resolve this significant use case! Please let us know as and when we can provide input on phase 2. We do urge the authors to take the time to find a shorter, more broadly understandable name. We also discussed the wider, and fundamental, issue of finding an alternative to IDREFs for expressing relationships between elements - we intend to explore this issue separately, and your feedback would be welcome on that thread. Should we set up a group to work on this issue, we will let you know. |
こんにちは TAG-さん!
I'm requesting a TAG review of Reference Target.
Reference Target is a feature that enables using IDREF attributes such as
for
andaria-labelledby
to refer to elements inside a component's shadow DOM, while maintaining encapsulation of the internal details of the shadow DOM. The main goal of this feature is to enable ARIA to work across shadow root boundaries.Further details:
You should also know that...
There have been a number of competing proposals in this area but little progress towards actually shipping solutions in browsers. See https://alice.pages.igalia.com/blog/how-shadow-dom-and-accessibility-are-in-conflict/.
For that reason this proposal is carefully scoped with the goal of identifying pieces of functionality with good prospects of reaching consensus such that they can be shipped and made available to developers, whose feedback will help inform additional work.
Hence, the proposal in the explainer is broken down into two phases. Phase 1 adds the ability to designate a single element as the target for all IDREF properties that refer to the host, while Phase 2 adds the ability to re-target specific properties individually. Breaking it down in this manner may allow us to reach consensus on Phase 1 while the more complex details of Phase 2 are still under discussion.
So if the TAG has feedback or concerns that apply to Phase 2 only, but is happy with Phase 1, it would be helpful for us if that is called out specifically so that Phase 1 can more easily move forward.
The text was updated successfully, but these errors were encountered: