Closed Bug 1919102 Opened 1 year ago Closed 1 year ago

Ship ARIA elements reflection

Categories

(Core :: Disability Access APIs, task, P3)

task

Tracking

()

RESOLVED FIXED
137 Branch
Tracking Status
relnote-firefox --- 136+
firefox136 --- fixed
firefox137 --- fixed

People

(Reporter: eeejay, Assigned: eeejay)

References

Details

(Keywords: dev-doc-complete)

Attachments

(1 file)

It is currently behind accessibility.ARIAElementReflection.enabled. That pref should be abolished when we are ready to ship.

No longer blocks: 1769586
Depends on: 1769586
Severity: -- → S3
Type: defect → task
Priority: -- → P3

This is the last unresolved issue for Interop 2024 Accessibility.
When will it ship?

Assignee: nobody → eitan
Status: NEW → ASSIGNED
Pushed by eisaacson@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/16ccfbf6810a Pref on aria elements reflection. r=dom-core,peterv

Comment on attachment 9464469 [details]
Bug 1919102 - Pref on aria elements reflection. r?#dom-core

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: This helps with our interop goals and brings these features closer to release.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: No
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): This feature has been available in Nightly for months.
  • String changes made/needed:
  • Is Android affected?: Yes
Attachment #9464469 - Flags: approval-mozilla-beta?
Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 137 Branch
Keywords: dev-doc-needed

Comment on attachment 9464469 [details]
Bug 1919102 - Pref on aria elements reflection. r?#dom-core

Approved for 136.0b5
:eeejay please add a release note request for this

Flags: needinfo?(eitan)
Attachment #9464469 - Flags: approval-mozilla-beta? → approval-mozilla-beta+

Release Note Request (optional, but appreciated)
[Why is this notable]: This adds new DOM API. It allows attributes like aria-labelledby and aria-controls to be set as DOM object properties referencing their target elements directly.
[Affects Firefox for Android]: Yes
[Suggested wording]: Added support for ARIA elements reflection
[Links (documentation, blog post, etc)]: https://wicg.github.io/aom/aria-reflection-explainer.html#reflecting-element-references

relnote-firefox: --- → ?
Flags: needinfo?(eitan)

Thanks, added to the Fx136 beta release notes, please allow 30 minutes for the site to update.
Keeping the relnote-firefox flag as ? to keep it on the radar for inclusion in the final Fx136 release notes.

Regressions: 1948025

MDN docs for this can be tracked in https://github.com/mdn/content/issues/38402

  1. Compatibility data testing for FF137 showed we implement these interfaces in this release. Is this correct/the full set? I've submitted a PR for the compatibility data to be moved to FF137

api.Element.ariaActiveDescendantElement
api.Element.ariaControlsElements
api.Element.ariaDescribedByElements
api.Element.ariaDetailsElements
api.Element.ariaErrorMessageElements
api.Element.ariaFlowToElements
api.Element.ariaLabelledByElements
api.Element.ariaOwnsElements
api.ElementInternals.ariaActiveDescendantElement
api.ElementInternals.ariaControlsElements
api.ElementInternals.ariaDescribedByElements
api.ElementInternals.ariaDetailsElements
api.ElementInternals.ariaErrorMessageElements
api.ElementInternals.ariaFlowToElements
api.ElementInternals.ariaLabelledByElements
api.ElementInternals.ariaOwnsElements

  1. Do any of these work across shadow boundaries?
    • In particular ariaOwnsElements looks like it shouldn't - see https://github.com/w3c/aria/issues/2266
    • When I declare aria-labelledby with a label outside of the DOM that isn't found when I log ariaLabelledByElements within the shadow dom:
      <span id="label_1">Street name</span>
      <div id="host">
        <template shadowrootmode="open">
          <input aria-labelledby="label_1 label_2" />
          <span id="label_2">(just the name, no "Street" or "Road" or "Place")</span>
        </template>
      </div>
      
    So my assumption is that you can't reference any elements in the other scope - i.e. you couldn't have a dom element set a shadow dom element with ariaActiveDescendantElement. But if you assign the DOM element, move it to the Shadow DOM and back, then it will remain linked. Right?
Flags: needinfo?(eitan)

Is "sprouting" of attributes from properties supported?

According to the explainer, we should be able to set attributes programmatically for element.ariaLabelledByElements and then get back the references using getAttribute() - provided the referenced elements are in the DOM and have an id.

This does not appear to work, at least on MDN. This code does not log the references:

<span id="label_1">Street name</span>
<input />
<span id="label_2">(just the name, no "Street" or "Road" or "Place")</span>
const inputElement = document.querySelector("input");
const label1Element = document.querySelector("#label_1");
const label2Element = document.querySelector("#label_2");

// Feature test for ariaLabelledByElements
if ("ariaLabelledByElements" in Element.prototype) {
  inputElement.ariaLabelledByElements = [label1Element, label2Element];

  log(`Labeled elements: ${inputElement.getAttribute("aria-labelledby")}`);
}

You can see this in action as the second example in https://pr38678.review.mdn.allizom.net/en-US/docs/Web/API/Element/ariaLabelledByElements#assign_the_accessible_name_programmatically

I'm also seeing the same result when I try set the active descendant programmatically - this causes getAttribute() to return an empty string.

Unfortunately, this detail was changed when this was formally specified, but the explainer wasn't updated accordingly. Now, per the spec, when you set one of these properties on a DOM node, the content attribute gets set to "", rather than the id of the target node.

<label id="label">My input</label>
<input id="input">
<script>
const input = document.getElementById("input");
const label = document.getElementById("label");
console.assert(!input.hasAttribute("aria-labelledby"));
console.assert(input.getAttribute("aria-labelledby") === null);
input.ariaLabelledByElements = [label];
console.assert(input.hasAttribute("aria-labelledby"));
console.assert(input.getAttribute("aria-labelledby") === "");
</script>

Thanks @James. I'd hoped the explainer would be correct enough to work as a good baseline. I'll try read the spec now.

Can you confirm if any of these relationships work across the shadow DOM boundary? My testing seems to show that any relationships set in the DOM or a shadow root are retained if you move an element in and out of the scope. However they don't apply "cross scope" - i.e. you can't set a DOM to have one of these references in a shadow root. Is that correct?

Apologies if you're not the right person to ask directly.

Flags: needinfo?(jteh)

(In reply to Hamish Willee from comment #13)

Thanks @James. I'd hoped the explainer would be correct enough to work as a good baseline. I'll try read the spec now.

Some parts of the spec are rather hard to read. I'm happy to help demystify it.

Can you confirm if any of these relationships work across the shadow DOM boundary?

The same rule applies to all of them. They work referring within the current scope or an ancestor scope, but not a descendant scope.

<div id="host">
  <template shadowrootmode="open">
    <div id="inner"></div>
  </template>
</div>
<div id="outer"></div>
<script>
const host = document.getElementById("host");
const inner = host.shadowRoot.getElementById("inner");
const outer = document.getElementById("outer");
outer.ariaLabelledByElements = [inner];
console.assert(outer.ariaLabelledByElements.length == 0);
inner.ariaLabelledByElements = [outer];
console.assert(inner.ariaLabelledByElements.length == 1);
</script>
Flags: needinfo?(jteh)

Thanks James! Doubtless I will - the spec if very hard to read.

when you set one of these properties on a DOM node, the content attribute gets set to "", rather than the id of the target node.

Ah, interesting. So these actually only initially reflect the value of the content attribute.

If you set the content attribute, that will overwrite whatever you last set with the IDL property, and vice versa. The most recently set always wins. If you set the IDL property, the content attribute will always be set to "".

Flags: needinfo?(eitan)

FYI, docs work pretty much done in https://github.com/mdn/content/pull/38678 - but it is being reviewed still.

Hi James. I had a follow-on query from a reviewer about the definition of the three scopes in "current scope or an ancestor scope, but not a descendant scope."

  • Are these terms that are defined in the/a spec or is this more of a convenient terminology you use for for describing the relationship between elements nested in different DOM/shadow DOM.
  • If they are in spec, is this terminology used broadly for shadow DOM discussions, or is it just used in reference to reflected element references.

It matters because it determines where I define and use the terms within MDN.

Flags: needinfo?(jteh)

I'll be really honest: I don't know. I find a lot of the terminology used to describe shadow DOM things kinda confusing myself and there is also some historical stuff that isn't in the spec but gets thrown around widely (I think "light DOM" might be one of these).

In terms of the spec, the correct terminology is that we should only return an element set by an ARIA IDL attribute if it "is a descendant of any of element's shadow-including ancestors". But... I struggle to make sense of that as a browser engineer, let alone a web developer, and so I don't know that it makes sense to put that on MDN. That's why I used various "scopes" to try to make it clearer, but I don't think that's actually a "spec" term.

Flags: needinfo?(jteh)

Hi James,

We just got an MDN issue report against the docs I created for this feature. Specifically the docs for element reference scope.

What they say (summarized) is that the scope of reference is "upwards" - an element in a shadow root can reference an element in the same root or any parent shadow or the DOM, but an element in the DOM can't reference downwards into a shadow DOM.

But as you can see, in the issue, the inspector shows that the element in the shadow is not finding the reference in the parent.

I am "somewhat sure" I tested this when it was written - but it doesn't work now. Did I misunderstand, or has something changed over the last 3 or so months since we did this?

Flags: needinfo?(jteh)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: