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

9.3 Presentational Roles Conflict Resolution does not consider custom element use cases #2303

Open
aleventhal opened this issue Aug 2, 2024 · 27 comments · May be fixed by #2383
Open

9.3 Presentational Roles Conflict Resolution does not consider custom element use cases #2303

aleventhal opened this issue Aug 2, 2024 · 27 comments · May be fixed by #2383
Assignees
Labels

Comments

@aleventhal
Copy link
Contributor

aleventhal commented Aug 2, 2024

Describe your concern

It's natural to provide ARIA properties on a custom element and then have the custom element implementation copy that property to a 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, and it could then place role="none" on the custom element to avoid 1) Having an extra element in the a11y tree with duplicate properties and 2) Using a name on the custom element which likely has a generic role -- name on generic is prohibited.

Currently the role="none" (or role="presentation") on the custom element is ignored because we are afraid of losing the semantics. However, it seems like a reasonable use case to me. I don't think custom elements should get their role="none" markup ignored when used with aria-foo properties. It should still ignore role="none" if it has a tabindex.

Link to the version of the specification or documentation you were looking at at.

https://w3c.github.io/aria

Link to documentation:

https://w3c.github.io/aria/#conflict_resolution_presentation_none

Does the issue exists in the editors draft (the editors draft is the most recent draft of the specification)?

Yes

UPDATE: please see also WICG/webcomponents#1073, to make role="none" the default role for custom elements, except when there is aria-owns or aria-live present, or it is focusable. This is issue is only about allowing role="none" on custom elements at all.

@scottaohara
Copy link
Member

Preemptively adding agenda to this so we can talk about it outside of triage

@aleventhal
Copy link
Contributor Author

I don't think I can make this week's meeting. Here is the harmful sentence in the spec:
"If an element has global WAI-ARIA states or properties, user agents MUST ignore the none/presentation role and instead expose the element's implicit role."

Basically, when there's a custom element, I want the "MUST ignore" clause to be invalidated, because it's natural for js libraries to use this (Material makes use of this technique). The js copies the ARIA attributes to an element inside of the shadow root. I want the js to then apply role="none" to the custom element, and for the UA to support that.

@jnurthen jnurthen added F2FCandidate Candidate topics for F2F (or Virtual F2F) meeting and removed Agenda labels Aug 8, 2024
@MelSumner
Copy link
Contributor

I spend a lot of time writing components and helping developers fix their components, and personally I would say this is author error.

I would like to advocate for a role for custom components so we can choose to handle those separately, rather than overloading an existing role.

@Westbrook
Copy link

Does this align with https://github.com/WICG/webcomponents/blob/gh-pages/proposals/reference-target-explainer.md wherein an element author has more finite control over the elements receiving the aria values?

@spectranaut
Copy link
Contributor

Discussed in ARIA working group meeting on Aug 8: https://www.w3.org/2024/08/08-aria-minutes#t05

@aleventhal
Copy link
Contributor Author

@spectranaut Can we put this on the agenda again for this week? I'm back from vacation.

@Westbrook
Copy link

@aleventhal
Copy link
Contributor Author

@Westbrook Unless the author set role=none on the custom element, it wouldn't have any effect.
I don't see the author doing that and also using an element relation to point inside of the shadow root via reference target, because if the custom element is copying the ARIA into elements inside of the shadow root, then those relations already don't need to cross-shadow root solution, as they are both originating and targeting elements inside of the shadow root.

@Westbrook
Copy link

In that case, I'm pretty sure that I'm misunderstanding your use case. Would you be able to share a more concrete example?

@aleventhal
Copy link
Contributor Author

Example:
<my-weird-checkbox aria-label="I like cats" aria-description="Think deeply about your relationship with cats">
...
In a constuctor or init code:

  • The aria-label and aria-description are copied to an inner <div role=checkbox>
  • this.role = 'none'; // Remove the original custom element from the a11y tree.

If the browser follows current rules, it must ignore the role=none and keep the custom element in the tree, thus causing 2 nodes to have the same label and description. We had that rule because nobody could think of a reason that you would need global ARIA attributes and role=none on the same element. I'd like to alter the rule now that we see a reason that authors do it.

@Westbrook
Copy link

Westbrook commented Aug 12, 2024

In that case, is it better for the author for the browser to ignore the combination of role="none" aria-label="..." on the assumption that they pass the value down for themselves or to discuss expanding Reference Target to manage absolute attributes as well, so that the author wouldn't need to manually pass those values?

I'm no browser implementor, but it would seem that whatever allows the label in this example to be passed through:

<label for="x-checkbox">I'm a checkbox</label>
<x-checkbox id="x-checkbox">
  <template
    shadowrootmode="open"
    shadowrootreferencetarget="real-input"
  >
    <input type="checkbox" id="real-input">
  </template>
</x-checkbox>

Could/should pass through the same when the code was:

<x-checkbox aria-label="I'm a checkbox">
  <template
    shadowrootmode="open"
    shadowrootreferencetarget="real-input"
  >
    <input type="checkbox" id="real-input">
  </template>
</x-checkbox>

@aleventhal
Copy link
Contributor Author

I'm not sure — we can study that. Is there any reason that we can't do what I propose as a solution for existing content that we have now? It wouldn't seem to invalidate other future solutions.

Put another way, we only didn't allow role="none" to ablate nodes from the tree when they had other ARIA properties, because we couldn't imagine a reason. Now that we can imagine a reason, this rule is doing harm and I'd like to remove the rule.

@break-stuff
Copy link

This also seems misleading if I explicitly set a role on the host element and the browser doesn't respect that.

It would be nice to allow the user to apply these attributes and allow us to map them to the appropriate internal shadow DOM elements. We have many teams that don't understand custom elements, so, rather than use our APIs, add their own aria attributes. Although this isn't a true replacement for the "reference targeting" that @Westbrook was referring to, it would be a nice safety net to provide a good user experience.

@spectranaut
Copy link
Contributor

Discussed in today's ARIA working group meeting: https://www.w3.org/2024/08/15-aria-minutes.html#t05

@Westbrook
Copy link

In that aria-label and aria-description, et al. are not reference attributes, they won't be applied via Reference Target in the currently discussed form. If role="none", I don't see much harm in my experience in removing an element from the AT and allowing it's custom implementation do to what it will with the values applied to them. There's certainly some author knowledge required around aria-label reflected to ariaLabel, etc. but if you're already doing the work to role="none" hopefully you'll be covering all of your bases for the rest of the functionality.

However, I do think that there is no great difference between an element getting labelled with aria-label and getting labelled with aria-labelledby and think that this should be handled in future iterations of Reference Target. To start that conversation, I've opened WICG/webcomponents#1068, which posits an even larger expansion of Reference Target to start, so that when it gets whittled down a bit we're likely to still get coverage for common sense items like those referenced in this issue.

@stes-acc
Copy link

stes-acc commented Aug 16, 2024

Is role="custom" (applied with some formal grammar mapping rules to avoid misuse) completely off the negotiation table?

I remember there was an old idea in the ARIA group (at 1.0 times) to allow custom roles (or role customization) using e.g. JSON notation. But this caused a can-of-worms discussion and the idea was abandoned.

In this sense, for a checkbox with additional properties authors could write

<div role="custom checkbox">

with attached JS fetch handler for JSON data that contains ARIA and custom attribute value pairs. Of course screen readers must be prepped to support this.

@jnurthen
Copy link
Member

jnurthen commented Aug 21, 2024

@aleventhal to summarise the proposal (unless I am over simplifying). We would add to the last bullet of the presentational roles conflict resolution section:

  • If an element has global WAI-ARIA states or properties, user agents MUST ignore the none/presentation role and instead expose the element's implicit role. However, if an element has only non-global, role-specific WAI-ARIA states or properties, the element MUST NOT be exposed unless the presentational role is inherited and an explicit non-presentational role is applied.

to become something like

  • If an element has global WAI-ARIA states or properties, user agents MUST ignore the none/presentation role and instead expose the element's implicit role unless the element is a custom element and has an explicit role=none/presentation. However, if an element has only non-global, role-specific WAI-ARIA states or properties, the element MUST NOT be exposed unless the presentational role is inherited and an explicit non-presentational role is applied.

@aleventhal
Copy link
Contributor Author

aleventhal commented Aug 21, 2024 via email

@jnurthen
Copy link
Member

jnurthen commented Aug 21, 2024

Yes James, that sounds good to me. Do we want to add some non-normative text explaining why the exception exists?

I think a note for this would be a good addition. I just want to clarify what we are discussing as a possibility. We'd obviously want to make sure that the other browser vendors are on board too.

@aleventhal
Copy link
Contributor Author

We should also have a default role of none for custom elements, unless they are focusable, have aria-owns, or aria-live.
See WICG/webcomponents#1073.
This seemed to get general support at TPAC. I have a couple of commits in Chromium waiting on official WG consensus.

@scottaohara
Copy link
Member

looking through the global html attributes that could be used on a custom element, seems they'd mostly fit in to the 'focusable' (e.g., tabindex, autofocus) category, or already have minimum role expectations for them (popover, draggable).

but what about title? not asking because i'm at all a fan of the attribute - but it's always been the odd one out with the presentational role conflict resolution, since it only ever outlined what to do for instances of an element being focusable, or having a global ARIA attribute, but no mention what to do with global (HTML) host language attributes.

my guess is that if it was ignored, it'd likely be information that people didn't have great access to in the first place, so maybe nothing lost? And for the instances of where attributes were being used for passing down into the internals of the custom element, it'd maybe be fine anyway. just probably worth making sure it's understood / called out so other people also don't wonder what is supposed to happen.

@aleventhal
Copy link
Contributor Author

aleventhal commented Oct 15, 2024

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

@stes-acc
Copy link

stes-acc commented Oct 24, 2024

What do we do if custom elements do try to EXTEND base roles? Shouldn't there a base role to be specified? Or should there be aria-roledescription used instead? Can we have this discussion less generic and more concrete example based?

@spectranaut
Copy link
Contributor

Discussed briefly in today's meeting: https://www.w3.org/2024/10/24-aria-minutes.html#e25e

@smhigley volunteered to open a PR with html-aam changes :)

@aleventhal
Copy link
Contributor Author

This isn't just about the original idea to allow role=none on custom elements, I don't think. Now it's also about having custom elements have a default role of none.

We should think about what is the best way to say this so that spec readers will understand it. I'm not sure that the presentational role conflict resolution is the best place. Maybe it needs to be there, but somewhere else as well. maybe it even deserves its own section, and needs HTML-AAM treatment.

As a high level thing in Chrome's prototype implementation, it is more about when to ignore custom elements. As in, "Ignore custom elements in the a11y tree with these exceptions (focus/owns/live)" rather than 1) give it a default role of none, and 2) change when we ignore role=none on custom elements. It probably comes out to the same thing. But, it may actually be worth considering that when to ignore custom elements is easier to understand than giving the conflict resolution section a complex treatment or list of exceptions. Again, we could do both. I'm just not sure readers would expect something so important to just be a set of fractally complex exceptions in the presentational conflict resolution section.

aarongable pushed a commit to chromium/chromium that referenced this issue Nov 21, 2024
…rom tree

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

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

See w3c/aria#2303

Bug: none
Change-Id: I34de182d6f93528049a6662f65c90c0119ba643b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5894644
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1386325}
@aleventhal
Copy link
Contributor 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.

@smhigley @jnurthen @scottaohara We need to update the HTML-AAM spec for the default role part, and the ARIA presentational roles conflict resolution to even allow role="none" on a custom element in the first place. Does anyone have cycles for it?

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.

CC'ing other implementers as well so that they know this is active. @cookiecrook @jcsteh

scottaohara added a commit that referenced this issue Nov 22, 2024
closes #2303

This updates a custom element's default role to none to allow attribute reflection from the custom element parent to its internals.

This change provides additional clarification about how a custom element can be provided a role by authors, and what caveats would change a custom element's default role of none, to another implicit minimum role.
@scottaohara scottaohara linked a pull request Nov 22, 2024 that will close this issue
6 tasks
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 <chrishtr@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1391105}
@aleventhal
Copy link
Contributor Author

The changes described in #2383 can now be tested in Chrome Canary 133.0.6876.0 or later by running with the command line parameter --enable-blink-features=AccessibilityCustomElementRoleNone.

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

Successfully merging a pull request may close this issue.

9 participants