WICG / webcomponents

Web Components specifications
Other
4.39k stars 375 forks source link

Web components authors are currently using ARIA in problematic ways that lead to duplicate announcements #1073

Open aleventhal opened 1 month ago

aleventhal commented 1 month ago

It's natural (and possibly common) for component implementations to copy ARIA properties from the custom element and then have the custom element implementation copy that property to a focusable descendant. For example, aria-label, aria-description or aria-placeholder could be provided by the author on the custom element. The custom element would then copy the ARIA properties to the actual input element in its subtree.

This is problematic because it would cause there to be duplicated properties on 2 objects in the a11y tree, which could lead to duplicate announcements or other strange behaviors in assistive technologies. For example, a screen reader like JAWS or NVDA with virtual buffer navigation would have two objects with the same label or description.

Unfortunately this pattern is already out there, and that means many many actual usages of the custom elements are already doing it. At this point it's too hard to get people to stop doing the pattern.

I appeal to the community to come up with creative solutions. I added an issue to the ARIA to allow role=none to be set on the custom element to remove it from the a11y tree (currently the spec/browsers require role=none to be ignored on elements that also have global ARIA attributes). Here's the issue I filed: https://github.com/w3c/aria/issues/2303

It could make sense to have a default role of none on custom elements (e.g. if there is no other role set). Do people think that this will cause backwards compatibility issues? I suppose it would fix the problem, so, it would be good to know if anyone foresees an issue with that.

smhigley commented 1 month ago

Dropping a thought here that was briefly talked about during the TPAC ARIA/Web components session:

If it's possible to add a default role based on the existence of referencetarget, or potentially some specific attributes defined in referencetargetmap. When those are defined, we may want to add a default role=none mapping to solve the duplicate/nested attribute issue mentioned here, but without always setting a default role none to differentiate between intentionally exposing a11y information on the custom element node.

I think this would ideally be done with an HTML AAM mapping rather than adding a literal role IDL attribute to the custom element, unless that isn't technically feasible.

I'm curious what other folks think, and also whether this is technically feasible and if so, what the logic to set the default role=none should be.

aleventhal commented 1 month ago

Thanks @smhigley, something like that could work. If the author doesn't supply their own role, we can guess role=none, unless the custom element itself is focusable, or has a global ARIA property that's likely to be used on a generic (in which case we would keep the current generic role mapping). By doing this and resolving https://github.com/w3c/aria/issues/2303, we would have a satisfactory solution for existing content.

For me, aria-live and aria-details seem like the only global ARIA properties that should undo the role=none default. But maybe it's not that important to support this exception, and we should just require the author provide a role if they don't want role=none for the custom element. If this is true, then I think we are just making a new default role for custom elements of "none". @smhigley WDYT?

Westbrook commented 1 month ago

Pardon the naiveté, are there/what are the functional differences between role="none" and role="generic"?

Were referenceTarget (in a theoretical Level 2) expanded not just to include referenceTargetMap but also to pass string based attributes to the referenced element as well, would you expect the element's role to revert back to the default role="generic" when doing so? Would the element reverting to role="generic" (being the attribute was no longer associated to it) resolve this situation, or would additional defaults still need updating across the related specification here?

aleventhal commented 1 month ago

role="none" (and its older synonym "presentation") cause an object to be removed from the a11y tree. By using that, and updating the presentational roles conflict section in the ARIA spec, we could avoid the duplicated semantics and announcements.

If referenceTarget, or some other theoretical ARIA property were invented that automatically passes ARIA attributes to an element inside of the custom element's implementation, I would expect that this is a great signal to remove the custom element from the AX tree to avoid duplication, and therefore an indicator that role="none" should be used for the custom element.

aleventhal commented 1 month ago

We're going to discuss this in the next ARIA WG meeting. During some informal discussions at TPAC, we had a consensus to change custom elements have a default role of "none", unless they are focusable or have aria-live or aria-owns, in which case they would have a default role of "generic". It's just the default role, so the author can always supply their own role.

aleventhal commented 1 month ago

CLs for Chromium/Blink: https://chromium-review.googlesource.com/c/chromium/src/+/5894644 (allow role="none" as in https://github.com/w3c/aria/issues/2303) https://chromium-review.googlesource.com/c/chromium/src/+/5894749 (default role of "none" as in this issue)