-
Notifications
You must be signed in to change notification settings - Fork 136
ARIA IDL updates: enumerated attribute conversions, new "enumerated" wai-aria type, IDL examples #2484
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for wai-aria ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
index.html
Outdated
<td class="value-description">The element does not support being checked.</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
<p>The attribute's <a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> and <a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> are both the Undefined state.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migrated comment from @keithamus (original):
I don't think we want the missing value default here to return the Undefined state, that will mean the .ariaChecked
property will return "undefined"
when aria-checked
isn't on the element. I presume we want to return null
instead? Browsers currently return null, so missing should be "no state", i.e. removed:
<p>The attribute's <a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> and <a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> are both the Undefined state.</p> | |
<p>The attribute has no <a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> and its <a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> is the Undefined state.</p> |
Thanks! I'll review those comments (which are migrated to this PR now) and respond. |
Re-added reviewers @pkra @spectranaut @cookiecrook @keithamus @scottaohara. |
… rahim/update-aria-idl-2025
CC @pkra @spectranaut @cookiecrook @keithamus @scottaohara @annevk This PR is ready for review! I've made a number of updates, mainly:
If helpful, I also created this tool to simulate how the new ARIA IDL works for enumerated attributes: https://rahimabdi.github.io/aria-idl-simulator/. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that's nice in HTML is that all the states are a <dfn>
and therefore also can be linked. But maybe that's best addressed in a follow-up.
Some ARIA attributes support an Undefined state, which is equivalent to having no state (i.e., null). User agent implementations may omit the Undefined state since the lack of an explicit | ||
state results in the same behavior. For more information about determining the state of enumerated attributes, see |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this sentence adds more confusion than it resolves. Especially since you cannot just leave it out at the moment without hitting an assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of this could be an informative note for authors/implementors, rather than in the normative text of the Enumerated Attribute definition.
Do we ever anticipate a time where the explicit "undefined" content attribute values would need to map to an Undefined state, separately than the Null state? For example, I think the only scenarios where an undefined
is allowed are with the undefined/true/false/[/mixed]
enumerated values, but since the Missing Default and Invalid Default are the same one those, there is no impact... Can we foresee any scenario where those would be different? For example, if undefined
was an allowed token value of aria-invalid
? (Presumably we just need to always avoid that, which seems okay.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See @keithamus' related comment in https://github.com/w3c/aria/pull/2484/files#r2084175913
Default values from the ARIA values tables MUST NOT reflect to IDL as the <a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> or the | ||
<a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> for the attribute. On getting, a missing ARIA attribute will return <code>null</code>. ARIA | ||
attributes are not validated on get. If an ARIA value is invalid, on getting, it will return its set value as a literal string, and will not return an invalid value default. | ||
For non-enumerated attributes, default values from the ARIA values tables MUST NOT reflect to IDL as the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems okay to state as a note, but it shouldn't be a requirement. HTML already requires this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
informative note
@@ -12761,7 +12802,7 @@ <h2>Definitions of States and Properties (all aria-* attributes)</h2> | |||
</tr> | |||
<tr> | |||
<th class="state-value-head" scope="row">Value:</th> | |||
<td class="state-value"><a href="#valuetype_tristate">tristate</a></td> | |||
<a href="#valuetype_enumerated">enumerated</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems better
<a href="#valuetype_enumerated">enumerated</a> | |
<td class="state-value"><a href="#valuetype_enumerated">enumerated</a></td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch @pkra
@aleventhal you may want to review this |
<td class="value-description"> | ||
When a user is providing input, an element containing a collection of values that could complete the provided input might be displayed. If displayed, one value in the collection is | ||
automatically selected, and the text needed to complete the automatically selected value appears after the caret in the input. | ||
</td> | ||
</tr> | ||
<tr> | ||
<th class="value-name" scope="row"><strong class="default">none (default)</strong></th> | ||
<th class="value-name" scope="row">none</th> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional that (default)
is dropped here? (And in 18 other instances.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a future enhancement for ARIA editors to avoid value error contradictions, perhaps the values table could be generated from the IDL? Or generate both the IDL and the values tables from the same pre-ReSpec source? (Not in this patch though. It's already massive.)
Discussed in today's meeting: https://www.w3.org/2025/05/08-aria-minutes.html#7d9a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm! this is much more clear, thank you
<p> | ||
For <a data-cite="html/common-dom-interfaces.html#reflect">reflection</a> purposes, the attribute's | ||
<a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> is the Undefined state (null) that has no associated keyword, and its | ||
<a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> is the False state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Blocking) So I believe this kind of change to the spec is web observable, which means it will need changes to the implementations and we need to ensure compatibility for web developers who may depend on the existing behaviour. Unless I am missing that somewhere we clarify that reflected enumerated properties should only return the value of the content attribute?
In this example the web observable piece is that the "invalid value default" is the False
state, which means that any invalid value would map to the False
(for which I presume the keyword is "false"
- see above).
This means pasting this HTML into your URL bar:
data:text/html,<body id=b><div id=d aria-atomic=foo><script>b.append(d.ariaAtomic)</script>
Should render false
on the page. But right now it renders foo
.
I think this will be the same for all of these properties, e.g. aria-autocomplete
, aria-checked
and so on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we should have tests for this and such, but this is very much the motivation for making this change. This makes these IDL attributes more meaningful and enables them to be used for feature testing going forward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For sure, I appreciate the motivation for it, I just want us to be cautious about introducing changes to the spec without getting tests & approval from the various engines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like we should add the tentative WPT tests, and implement in engines behind a runtime flag to review potential impact on the Salesforce polyfill (Keith recalled this example) and any other places this might affect webcompat. @nolanlawson FYI ^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed Nolan is no longer at SalesForce. Please copy any relevant contact if you know who should review. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<td class="value-description">The element is checked.</td> | ||
</tr> | ||
<tr> | ||
<th class="value-name" scope="row"><strong class="default">undefined</strong> (default)</th> | ||
<th class="value-name" scope="row">undefined, empty string ("")</th> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Non-blocking) We could reasonably drop the undefined
keyword here:
<th class="value-name" scope="row">undefined, empty string ("")</th> | |
<th class="value-name" scope="row">empty string ("")</th> |
If someone set "undefined"
then it would map to the invalid value default, which is the undefined state. The only reason not to do this is if you want the canonicalization steps to explicitly return undefined
rather than the empty string.
The same is true for other properties, e.g. aria-current
, and so on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great callout! We can simplify many attributes, i.e., empty value and/or undefined map to an invalid value default:
I've also included the "empty value default" which is helpful for boolean-like declaration of ARIA attrs (e.g., <div someAttr>; this could be a WebIDL extended attribute like [EmptyValueDefault] and where it's not null, it could provide an extra state for the attribute.
Simplifying enumeration for attributes:
- aria-atomic
- Remove empty string keyword as it maps to “false” state
- Empty value default = “false”
- aria-busy
- Remove empty string keyword as it maps to “false” state
- Empty value default = “false”
- aria-checked
- Remove empty string and undefined keywords as they maps to null (invalid value default)
- Empty value default = null
- aria-current
- Can’t remove empty string because IVD = “true”
- Empty value default = “false”
- Undefined string maps to “true”
- For implementation, this one needs manual reflection (i.e., can't use a nice WebIDL extended attribute like [ReflectEnum]
- aria-disabled
- Remove empty string keyword as it maps to “false” state
- Empty value default = “false”
- aria-expanded
- Both empty value and undefined map to null (invalid value default)
- Empty value default = null
- aria-hidden
- Both empty value and undefined map to false state "invalid value default”
- Empty value default = “false”
- Undefined maps to “false” which is IVD
- aria-invalid
- Empty value default = “false”
- aria-modal
- Empty value default is “false”, however it’s also covered by invalid value default so can be removed
- aria-multiline
- Empty value default is “false”, however it’s also covered by invalid value default
- aria-multiselectable
- Empty value default is “false”, however it’s also covered by invalid value default
- aria-orientation
- Both “” and undefined could be covered by invalid value default (null)
- Empty value default = null
- aria-pressed
- Both empty string and undefined could be covered by invalid value default (null)
- Empty value default = null
- aria-readonly
- Empty value default is “false”, however it’s also covered by invalid value default
- aria-required
- Empty value default is “false”, however it’s also covered by invalid value default
- aria-selected
- Both “” and undefined could be covered by invalid value default
- Empty value default = null
Discussed briefly: https://www.w3.org/2025/06/26-aria-minutes.html#768c Next step to write tentative tests? |
<a href="#valuetype_true-false">true/false</a>, <a href="#valuetype_true-false-undefined">true/false/undefined</a>, <a href="#valuetype_tristate">tristate (true/false/mixed)</a>, a | ||
single named <a href="#valuetype_token">token</a>, or a <a href="#valuetype_token_list">token list</a>. | ||
Used in an attribute description to denote that the value <a href="#propcharacteristic_value">type</a> is a named token or otherwise token-like, including a single named | ||
<a href="#valuetype_token">token</a>, a <a href="#valuetype_token_list">token list</a>, or <a href="#valuetype_enumerated">enumerated</a>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to leave a note about token true/false being Boolean-like but not a true Boolean? I recall adding this adjective to the above removal because some implementors and web devs assumed/wanted/thought the true/false values would/should behave like HTML boolean attributes.
I agree with your shorter definition as you have it, but consider whether an additional editorial note may head-off future questions.. For example, from @sideshowbarker regarding the LadyBird implementation.
Some ARIA attributes support an Undefined state, which is equivalent to having no state (i.e., null). User agent implementations may omit the Undefined state since the lack of an explicit | ||
state results in the same behavior. For more information about determining the state of enumerated attributes, see |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of this could be an informative note for authors/implementors, rather than in the normative text of the Enumerated Attribute definition.
Do we ever anticipate a time where the explicit "undefined" content attribute values would need to map to an Undefined state, separately than the Null state? For example, I think the only scenarios where an undefined
is allowed are with the undefined/true/false/[/mixed]
enumerated values, but since the Missing Default and Invalid Default are the same one those, there is no impact... Can we foresee any scenario where those would be different? For example, if undefined
was an allowed token value of aria-invalid
? (Presumably we just need to always avoid that, which seems okay.)
<p> | ||
All ARIA attributes reflect in IDL as [=nullable type|nullable=] {{DOMString}} attributes. This includes the boolean-like <a href="#valuetype_true-false">true/false</a> type, and all other | ||
ARIA attributes. | ||
An ARIA attribute may reflect as one of several IDL attribute types such as [=nullable type|nullable=] {{DOMString}}, [=nullable type|nullable=] {{FrozenArray}} or [=nullable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An ARIA attribute may reflect as one of several IDL attribute types such as [=nullable type|nullable=] {{DOMString}}, [=nullable type|nullable=] {{FrozenArray}} or [=nullable | |
An ARIA attribute may reflect as one of several IDL attribute types, such as [=nullable type|nullable=] {{DOMString}}, [=nullable type|nullable=] {{FrozenArray}} or [=nullable |
Default values from the ARIA values tables MUST NOT reflect to IDL as the <a data-cite="html/common-microsyntaxes.html#missing-value-default">missing value default</a> or the | ||
<a data-cite="html/common-microsyntaxes.html#invalid-value-default">invalid value default</a> for the attribute. On getting, a missing ARIA attribute will return <code>null</code>. ARIA | ||
attributes are not validated on get. If an ARIA value is invalid, on getting, it will return its set value as a literal string, and will not return an invalid value default. | ||
For non-enumerated attributes, default values from the ARIA values tables MUST NOT reflect to IDL as the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
informative note
<section class="informative" id="enumeration-example"> | ||
<h4>Example Attribute Usage</h4> | ||
<aside class="example"> | ||
<!-- ReSpec needs these examples to be unindented. --> | ||
<pre class="example highlight javascript"> | ||
<pre> | ||
// aria-label example (non-enumerated attribute) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// aria-label example (non-enumerated attribute) | |
// aria-label example (non-enumerated nullable DOMString attribute) |
// aria-busy example | ||
// true/false ~ boolean-like nullable string; returns null unless set | ||
<pre> | ||
// aria-busy example (enumerated attribute) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// aria-busy example (enumerated attribute) | |
// aria-busy example (enumerated attribute) | |
// the initial example's true/false tokens here are not true Boolean values. |
<td class="value-description"> | ||
When a user is providing input, an element containing a collection of values that could complete the provided input might be displayed. If displayed, one value in the collection is | ||
automatically selected, and the text needed to complete the automatically selected value appears after the caret in the input. | ||
</td> | ||
</tr> | ||
<tr> | ||
<th class="value-name" scope="row"><strong class="default">none (default)</strong></th> | ||
<th class="value-name" scope="row">none</th> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a future enhancement for ARIA editors to avoid value error contradictions, perhaps the values table could be generated from the IDL? Or generate both the IDL and the values tables from the same pre-ReSpec source? (Not in this patch though. It's already massive.)
@@ -12761,7 +12802,7 @@ <h2>Definitions of States and Properties (all aria-* attributes)</h2> | |||
</tr> | |||
<tr> | |||
<th class="state-value-head" scope="row">Value:</th> | |||
<td class="state-value"><a href="#valuetype_tristate">tristate</a></td> | |||
<a href="#valuetype_enumerated">enumerated</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch @pkra
Some ARIA attributes support an Undefined state, which is equivalent to having no state (i.e., null). User agent implementations may omit the Undefined state since the lack of an explicit | ||
state results in the same behavior. For more information about determining the state of enumerated attributes, see |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See @keithamus' related comment in https://github.com/w3c/aria/pull/2484/files#r2084175913
Closes #2281
Closes #2279
If helpful, I also created this tool to simulate how the new ARIA IDL works for enumerated attributes: https://rahimabdi.github.io/aria-idl-simulator/.
<strong>
style from old "defaults" valuesTest, Documentation and Implementation tracking
Once this PR has been reviewed and has consensus from the working group, tests should be written and issues should be opened on browsers. Add N/A and check when not applicable.
Preview | Diff