Skip to content
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

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

Open
aleventhal opened this issue Sep 25, 2024 · 8 comments

Comments

@aleventhal
Copy link

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: w3c/aria#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
Copy link

smhigley commented Sep 25, 2024

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
Copy link
Author

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 w3c/aria#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
Copy link
Collaborator

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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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

@aleventhal
Copy link
Author

Starting in Chromium 133.0.6852.0 (currently in Canary), you can run Chrome/Edge with the command --enable-blink-features=AccessibilityCustomElementRoleNone. It changes custom elements to use a default role of none, meaning that the custom element will be removed from the a11y tree, with these exceptions:

  • is focusable
  • has aria-live,
  • has aria-owns
  • uses element internals to set an ARIA property
  • uses an ARIA relation via an element attribute (e.g. myCustomElement.ariaLabelledByElements = [ labelElement ]; )

Since it's a default role, that means it only takes place if the author did not provide their own role for the element.

If I don't hear any objections, I'll update to "experiment" stage which turns it on when "experimental web platform features" is enabled in chrome://flags.

aarongable pushed a commit to chromium/chromium that referenced this issue Dec 3, 2024
Update custom role rules and tests based on new text at
w3c/aria#2383

Behind feature flag:
--enable-blink-features=AccessibilityCustomElementRoleNone

Intent to prototype / chromestatus entry:
https://chromestatus.com/feature/5079996916563968?gate=5150348547981312

Bug: w3c/aria#2303
Bug: WICG/webcomponents#1073
Bug: 379674023
Change-Id: If317916b432bc5a627c8ea6fa0654e6c98a10ea6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6042465
Reviewed-by: Chris Harrelson <[email protected]>
Commit-Queue: Aaron Leventhal <[email protected]>
Auto-Submit: Aaron Leventhal <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1391105}
@aleventhal
Copy link
Author

This change to using a default role of "none" to remove these elements from the a11y tree can now be tested in Chrome Canary 133.0.6876.0 or later by running with the command line parameter --enable-blink-features=AccessibilityCustomElementRoleNone. Scott O'Hara also opened up a spec PR for this change: w3c/aria#2383

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants