feat: aria-actions addition to the ARIA spec - #1805
Conversation
|
Adding reviewers to get some more perspectives on this. The description is missing in the PR, but the relevant discussion is in #1440, and I think the idea is sound. |
|
@smhigley I updated the property description to move this along. Nearly ready IMO. Some comments in the diff. |
mcking65
left a comment
There was a problem hiding this comment.
I think we need a discussion of whether aria-actions should be allowed on elements that are not focusable or referenced by aria-activedescendant. I see potentially big problems with elements that are containers with boundaries that screen readers treat as invisible. I also am concerned about the idea that it could be used on a dialog, which by default, should not be focusable; that is only a fall-back error condition where a dialog would get focus.
I have added several suggestions where I think the language needs more clarity.
|
To what extent is avoiding creating additional vectors for the active finger printing mentioned in section 11 a consideration in the design of this feature? I see some language that appears to be aimed in that direction, such as the requirement for using clicks and default actions. However, as written, it appears to me that it is all author responsibility, and is thus a wide open door. I wonder if it would be possible to have requirements that:
|
|
Matt, why do we need the focusable rule? Would it not be enough for the source to be visible, and the target to be visible & clickable? To activate the action, the browser can send it a click as if a real mouse click occurred. |
I think you may misunderstand. If an author doesn't use a click, it won't reveal anything new about the user. The UI just may not work in some scenarios. We purposefully limited AT's trigger-ability here to a click (rather than a new event or direct API call) to avoid risk of detection. |
Those are all much too rigid/restrictive in my opinion. And possibly too screenreader specific. AT focus or focus-in is an expectation, but not DOM focus. Otherwise we may not be able to make this work well for other AT like Switch Control, Voice Control, etc. Likewise Dragon on Windows, Android's Switch Access, etc. |
|
Are there any open questions with this functionality that needs any help? |
|
What else is needed to get this PR merged? |
|
@mrhbs wrote:
|
|
@mcking65 The latest changes introduced to respec are severely affecting the ARIA previews. We do need the latest updates for them to work properly. For fixing the conflicts I would prefer for @smhigley to take a pass at the main index.html file because it seems it's been a long time since we last merged main into this feature branch and conflicts are very long, which makes it difficult to resolve them with a screen reader. |
janewman
left a comment
There was a problem hiding this comment.
Thanks for putting this together, just a quick question
| <li>`nActions`: add the number of accessible nodes referenced by `aria-actions` that are exposed in the accessibility tree</li> | ||
| <li>`name`: if the corresponding target node has a DOM id, return that DOM id prefixed by "custom_". Otherwise, return "custom".</li> | ||
| <li>`localizedName`: return the corresponding target node's accessible name.</li> | ||
| <li>`doAction`: behave as if `doAction(0)` were called on the corresponding target accessible node.</li> |
There was a problem hiding this comment.
What about description and keyBinding? Do we want to specify the expected value? (even if that is S_FALSE)
https://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/interface_i_accessible_action.html
There was a problem hiding this comment.
Good question. The behaviour of IAccessibleAction::description and ::keyBinding is currently undocumented in the spec even for the primary action, let alone secondary actions... and that's before we even get to aria-actions. :) To make matters worse, Gecko and Chromium seem to disagree a little about how these should behave for both types of actions.
Although a lack of documentation for one case isn't a good excuse for failing to document another case, we're somewhat constrained here in that we're using the same interface for both sets of actions. For example, I think it'd be kinda weird if we returned E_NOTIMPL for description(0), but returned a useful string or S_FALSE for description(1).
For what it's worth, Gecko maps description(n) directly to localizedName(n). Chromium returns E_NOTIMPL for description(n) in all cases. I don't think there's anything useful we can do for description, so I don't feel strongly about any particular mapping.
keyBinding is messier. Gecko returns S_FALSE for n == 0, E_INVALIDARG for n >= 1. Chromium returns the access key (but just the key itself, not the modifier; e.g. b, not alt+b) for primary/secondary actions, but returns E_INVALIDARG for aria-actions. There probably is some utility in exposing the keyboard shortcuts associated with aria-actions, so perhaps we should make keyBinding(0) equivalent to this->accKeyboardShortcut and keyBinding(ariaActionIndex) equivalent to ariaAction->accKeyboardShortcut.
There was a problem hiding this comment.
@jcsteh do you think the keybinding should be spec'd or come from the browser? I was thinking about it, and wondering if this should be mapped in the API or left undefined to allow NVDA/JAWS to choose whatever makes sense independently. But obviously would defer to your opinion there.
There was a problem hiding this comment.
A thing to keep in mind here is that IAccessible2 clients can't get at the target node. They can only perform the action (doAction) and query the properties exposed by this interface: name, localizedName, description and keyBinding. So, if we don't expose the key binding for the target, the client can't get at it any other way.
Whether the client will use that is an open question. I guess I could see a use case where the client presents a menu of actions, and in that menu, the client shows the action name as well as the key binding, effectively allowing the client to "discover" the key binding for quicker access to the action next time. That seems like it could be useful.
I can't see any harm in exposing it; we're not doing anything with this method right now. So unless someone else can see a downside, I guess we should just do it.
Something like this:
<li>`keyBinding`: return the corresponding target node's keyboard shortcut; i.e. as if `accKeyboardShortcut` were queried on the corresponding target accessible node.</li>
There was a problem hiding this comment.
Oh, are you talking about using it to map any author-defined keyshortcuts on the action? That makes sense to me, I thought you meant making up a specific default keyboard shortcut for aria-actions and putting that there, which I didn't really see a reason to do.
There was a problem hiding this comment.
Oh, are you talking about using it to map any author-defined keyshortcuts on the action?
Yes. This would also apply to accesskey, since accesskey is also mapped to accKeyboardShortcut.
I thought you meant making up a specific default keyboard shortcut for aria-actions and putting that there, which I didn't really see a reason to do.
Oh, I can see why that would have been confusing. That's a terrible idea and definitely not what I intended to suggest. 😂
There was a problem hiding this comment.
haha awesome, then what you're saying makes complete sense to me, I'll update the mapping :D
Fix two IAccessibleAction methods that didn't properly handle aria-actions indices: - get_description: was returning E_NOTIMPL unconditionally. Now validates the action index and returns S_FALSE (no description available for any action type today). - get_keyBinding: was bounds-checking against existing actions only (things like kDoDefault (click), kFocus, kScrollUp) causing valid aria-actions indices to return E_INVALIDARG. Now includes aria-actions in the bounds check. I've raised a comment in the Spec PR for these mappings to be explicit: w3c/aria#1805 (comment) With these fixes, all six IAccessibleAction methods properly handle the full action index range (existing actions + aria-actions). Bug: 514751946 Change-Id: Icd1088913e21fca42f616abf66c04f69d808a19c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7896745 Auto-Submit: Jacques Newman <janewman@microsoft.com> Commit-Queue: Jacques Newman <janewman@microsoft.com> Reviewed-by: Benjamin Beaudry <benjamin.beaudry@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1640359}
| <th><abbr title="User Interface Automation">UIA</abbr></th> | ||
| <td> | ||
| <span class="property"> | ||
| Custom Property: <code>AccessibleActions</code>, an element array of accessible nodes matching IDREFs. If the referenced nodes are in the accessibility tree, expose the property using the following custom property registration information: |
There was a problem hiding this comment.
According to Microsoft documentation, we don't have the option to use UIAutomationType_ElementArray :(
A custom property must have one of the following data types specified by the UIAutomationType enumeration. No other data types are supported for custom properties.
- UIAutomationType_Bool
- UIAutomationType_Double
- UIAutomationType_Element
- UIAutomationType_Int
- UIAutomationType_Point
- UIAutomationType_String
That all said, on my windows 11 VM, using UIAutomationType_ElementArray works just fine, but doesn't in the chromium win10 bots, so maybe this is changing? Accessibility Insights wasn't able to reflect the custom property when it returned an element array either, but a local test UIA client implementation had no such issue.
There was a problem hiding this comment.
Heh, I pointed out the same thing in #1805 (comment). Apparently, this is a documentation oversight; see #1805 (comment):
I checked with Doug Geoffray, and it looks like it's just an oversight in the documentation. I believe any of the listed types can also be used as an array type for a property value.
We should be good to go to create AccessibleActions as a UIAutomationType_Element[] array 👍
There was a problem hiding this comment.
Heh yes, I checked with Doug when I originally wrote the mapping, then again when Jamie asked :D
I have no idea who owns that documentation but I suppose at this point I should probably try to find out
There was a problem hiding this comment.
This certainly appears to be a change with win11, on win10 this doesn't appear to work.
I'll agree that this documentation should be updated.
Do we need to call out that this won't work on older versions of windows? Given Windows 10 is past the support date, maybe we don't need to worry.
There was a problem hiding this comment.
yeah I wouldn't really stress about it as long as it would just fail to map aria-actions without causing any other errors.
mcking65
left a comment
There was a problem hiding this comment.
Three Editorial suggestions for clarity.
| <pdef>aria-actions</pdef> | ||
| <div class="property-description"> | ||
| <p><a>Identifies</a> a related element or elements whose primary activation (<code>click</code> event) will trigger a behavior or operation relevant to the referencing user interface object, such as the close button for a tab, or a reply button relevant to the email message that references it.</p> | ||
| <p>The <code>aria-actions</code> attribute allows an element to reference other interactive elements that trigger actions related to the referencing element. For example, in the inbox of a web mail application, the focused element representing an email message could reference buttons that perform actions on that email, such as Reply, Forward, and Delete. Actions are triggered by pointer events (click, tap) that can be simulated by assistive technologies.</p> |
There was a problem hiding this comment.
| <p>The <code>aria-actions</code> attribute allows an element to reference other interactive elements that trigger actions related to the referencing element. For example, in the inbox of a web mail application, the focused element representing an email message could reference buttons that perform actions on that email, such as Reply, Forward, and Delete. Actions are triggered by pointer events (click, tap) that can be simulated by assistive technologies.</p> | |
| <p>The <code>aria-actions</code> attribute allows an element to reference other interactive elements that trigger actions related to the referencing element. It is particularly useful for exposing contextual actions to assistive technology users in scenarios where action buttons become visible on hover or focus. For example, in the inbox of a web mail application, the focused element representing an email message could reference buttons that perform actions on that email, such as Reply, Forward, and Delete. Actions are triggered by pointer events (click, tap) that can be simulated by assistive technologies.</p> |
There was a problem hiding this comment.
I don't actually know if we want to call out hover/focus actions as being a better fit for aria-actions than statically available actions -- I think it's often just as needed for the latter in cases where you'd expect a user to be navigating in forms mode and not discover buttons that are not arrow stops in the menu/listbox/tablist/etc.
The latest spec PR(w3c/aria#1805) requires has-actions to be exposed on every host whose role supports aria-actions and that sets the attribute, regardless of whether any referenced target survives IsValidAriaActionsTarget. Widen the kHasActions gate in AXObject::SerializeUnignoredAttributes so the attribute is added when aria-actions is set on a supporting role, in addition to the existing path that triggers when kActionsIds is non-empty (which covers implicit-actions on menuitem-like roles). The previous gate keyed only on a non-empty kActionsIds, leaving assistive tech unable to distinguish "no aria-actions" from "aria-actions present but all targets filtered." Bug: 408040289, 514751946 Change-Id: Id621008fefd84a8b999565049735ff2c6f47a6a4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7895414 Reviewed-by: Benjamin Beaudry <benjamin.beaudry@microsoft.com> Commit-Queue: Jacques Newman <janewman@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1641975}
|
🚀 Deployed on https://deploy-preview-1805--wai-aria.netlify.app |
|
🚀 Deployed on https://deploy-preview-1805--wai-aria.netlify.app |
|
🚀 Deployed on https://deploy-preview-1805--wai-aria.netlify.app |
|
🚀 Deployed on https://deploy-preview-1805--wai-aria.netlify.app |
In creating the [aria-actions PR](w3c/aria#1805), it came up that the list of supported value types for a custom UIA property didn't include arrays, even though arrays are supported. This PR updates the docs to explicitly include the respective array types for each of the supported types.
The aria-actions spec PR (w3c/aria#1805) §6.8 includes an Author SHOULD that targets be visible when the host has DOM focus. Today we gave this behavior is chromium due to CanSetFocusAttribute() returning false for the hidden subtree, and IsValidAriaActionsTarget() already rejects targets that are not keyboard-focusable. This change codifies the existing behavior to protect against regression, with no behavioral change. Bug: 408040289 Change-Id: I12e4bc2bd8f2b1cac9f96dbcac1979ea085c3604 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7852706 Commit-Queue: Kurt Catti-Schmidt <kschmi@microsoft.com> Reviewed-by: Kurt Catti-Schmidt <kschmi@microsoft.com> Auto-Submit: Jacques Newman <janewman@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1651177}
…PG test Prohibit aria-actions on the 11 name-prohibited roles per w3c/aria#1805, add an allowEmpty pass case, and bump aria-practices to re-enable the tabs-actions APG example. aria-required-children / nested-interactive don't yet support the aria-actions pattern, so they're disabled per-page pending #5215. Closes #4584
## Summary Adds `aria-actions` to axe-core's known ARIA attributes so it is recognized as valid, allowed, and prohibited on the roles the spec prohibits it on — and re-enables the APG `tabs-actions` example that had been disabled for lack of `aria-actions` support. Per the [spec draft](w3c/aria#1805), `aria-actions`: - **Value type:** ID reference list → `idrefs` - **Global:** yes (like `aria-describedby`) - **Empty allowed:** yes — the spec permits `aria-actions=""` (the deferred-DOM case) → `allowEmpty: true` - **Prohibited roles:** the name-prohibited roles the spec also prohibits it on (all axe `prohibitedAttrs` roles except `none`/`presentation`, which the spec still permits) - **ElementInternals reflection:** `ariaActionsElements` ## Accessibility-supported rationale Following the [Impact on ARIA](https://github.com/dequelabs/axe-core/blob/develop/doc/accessibility-supported.md#impact-on-aria) decision framework: 1. Supported by all platforms? No — shipped in WebKit and Firefox; **Chromium pending**. 2. Does its use negatively impact accessibility? **No** — unsupported browsers simply ignore the attribute (progressive enhancement), and the spec hard-guards exposure. → **allow.** > **Note for reviewers:** the ARIA spec change is still [PR #1805](w3c/aria#1805), not yet merged — this aligns to the two engines shipping ahead of spec approval. We can patch the config later in the unlikely event the spec shifts. ## Changes **Attribute recognition** — `lib/standards/aria-attrs.js`: add the `aria-actions` entry (`idrefs`, global, `allowEmpty`). **Prohibited-on-role** — `lib/standards/aria-roles.js`: add `aria-actions` to `prohibitedAttrs` for `caption`, `code`, `deletion`, `emphasis`, `insertion`, `mark`, `paragraph`, `strong`, `subscript`, `superscript`, `suggestion`. Per [w3c/aria#1805](w3c/aria#1805) these roles prohibit it; `none`/`presentation` do not, so they are left unchanged. **APG test re-enable (Closes #4584)** — bump `aria-practices` to latest `main` (the `tabs-actions` page did not exist at the previously pinned commit) and remove it from `skippedPages`. axe recognizes the attribute but not the authoring *pattern*, so `aria-required-children` (tabs-actions) and `nested-interactive` (listbox-actions) are disabled per-page pending #5215. **Review feedback** — update the stale `wai-aria-1.1` `Source:` comment to the unversioned WAI-ARIA URL; add an `aria-actions=""` pass case exercising `allowEmpty`. ## Testing - `get-global-aria-attrs`, `aria-prohibited-attr` (check + virtual-rule), `aria-valid-attr`, `aria-allowed-attr`, `aria-valid-attr-value` unit + integration tests ✓ - Full APG suite green (76 passing) ✓ - `npm run build` clean; no auto-generated committed files change ## Follow-ups - #5215 — teach `aria-required-children` / `nested-interactive` about the `aria-actions` pattern, then remove the per-page disables in `apg.spec.js` Closes #5199 Closes #4584
🚀 Netlify Preview:
🔄 this PR updates the following sspecs:
Resolves #1440 by adding the
aria-actionsattributeThis has a dependency on the changes in #1454.
PR tracking
Check these when the relevant issue or PR has been made, OR after you have confirmed the
related change is not necessary (add N/A). Leave unchecked if you are unsure. Read the
Process Document or
Test Overview for more information.
Related Core AAM Issue/PR: included in this PRTest, Documentation and Implementation tracking
Once this PR and all related PRs have been been approved by the working group, tests
should be written and issues should be opened on browsers. Add N/A and check when not
applicable.
Preview | Diff