-
Notifications
You must be signed in to change notification settings - Fork 125
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
AccName Role Traversal Proposal #1821
Comments
appreciate you outlining all this, as it's giving me something to wrap my head around in a much easier way. Though with that said, in regards to the above i'm unclear what would happen with the following use case i mentioned in the our last WG meeting
i see article is mentioned as never traversable, so, would this not still produce a link without an accessible name? if so, maybe there needs to be another designation? Unless "only when focusable" doesn't necessarily refer just to the element, if focusable, but also a parent/ancestor element that would be nameless otherwise? I realize you said that the lists are not set in stone, but yeh, i'm not sure i understand how some roles like Thanks again for the work on this Bryan. Regardless of my questions/comments above, i'm sure this'll help move us forward. |
Actually article was part of the list originally proposed by Aaron back in 2017, which is what I am basing this list on mainly since I don't have time to take the Chrome code apart to see what it's doing. If others in the group agree to move this into the When Focusable category, I will abide by whatever people can agree on. The same goes with the rest of the roles. |
Where is generic in this list? |
That's one I forgot, generic should be in the Always category. |
The third category in Chrome is: |
I was mainly thinking of screen readers like JAWS that use a virtual buffer model that does not follow focus. If this were changed to only when it receives focus, it would break Scott's example in all cases such as when pressing Insert+F7 to get a list of all links on the page. |
So there are 2 parts to this. Roles that can have their own accessible name and roles that can only contribute to an ancestor's accessible name (for 2F). We need to cover both parts of this. |
"So there are 2 parts to this. Roles that can have their own accessible name and roles that can only contribute to an ancestor's accessible name (for 2F)." As far as I know this is already covered. "Name from author" already specifies if a role is namable, "Name from content" specifies if it can receive a general name using it's content, and "Traversable" would only specify if it can be traversed in 2F. |
In case it helps I exported https://searchfox.org/mozilla-central/source/accessible/base/RoleMap.h#1 into a google sheet at https://docs.google.com/spreadsheets/d/1iLk-KTX2PZvqIhdhQzM9vfMI3za3RlWQCRNx1e6m2VM/edit?usp=sharing
I could look through the code to work out exactly what each of these means but maybe @jcsteh can fill this in. |
This effectively maps to Name from: author, Traversable: always.
This effectively maps to Name from: content, Traversable: always.
This deals with 2C of the AccName spec:
This effectively maps to Name from: author (or prohibited), Traversable: never.
Note that Gecko does not currently support this concept at all. Overall, I think it makes sense. However, one problem is that "focusable" can mean a few different things:
|
FWIW, I don't think we could reasonably support Traversable: when focusable in Gecko until this issue is sorted out. |
Since this is simply a proposal, I expected some shifting based on backend limitations. If "When Focusable" were changed to "When Focused To", would you be able to support it? |
I think the problem is more complex and the following things should be clarified in AccName:
However, the rules outlined here are probably too complex, on the one hand, to implement consistently in browsers and, on the other hand, for web developers to apply them correctly. It would be much simpler to abandon the concept that an element cannot have an AccName and say that the text content is always the AccName (for elements that do not have Name from Author, like a div). |
It would be easier to support, but I don't think it's what we want. Whether something is focused is a lot more transient than whether something is focusable. Thus, the name would potentially change quite often, requiring a lot of extra name change events. On further reflection, I also realised I misunderstood the purpose of this "when focusable" rule. If I'm reading your proposal correctly, you're suggesting this only relates to aria-labelledby/describedby traversals and not "Name from: content". I'm curious as to why we want something to be traversed when focusable for aria-labelledby/describedby, but not not when calculating name from content. For aria-labelledby/describedby, I would've thought they should just always be traversed for those roles, whereas we probably do want them to be included in name from content only when focusable. |
I don't know what to do with this then. This is not just for aria-labelledby and aria-describedby traversals, but for any child node traversal that involves step 2H. We have to find a way of documenting how this is implemented in the browsers, because currently the only thing the spec says is to recursively start at 2F.i when traversing all child nodes, and this will not work correctly for all element and role types. E.G. A heading is a simple example of why, for example if it includes an embedded menu that is rendered inline with a triggering element within the heading. Also a tree using the same concept, or a standard select element such as a country selector that has over 280 options within it. If you apply 2H as it is currently written, skipping only to 2F.i, then name from content is skipped and everything must be included as the heading name regardless what type of role it is. Is this really what you want to happen? |
Let's put aside the precise definition of focusable, focused, etc. for a moment.
|
We spoke about this at the last ARIA meeting, and I think it would be beneficial for us to have a deep dive meeting to hash out what is or is not possible from the implementer perspective and the issues being addressed. Would you @jcsteh be willing to attend that? Ideally this would also include @aleventhal and @cookiecrook as well so we can work this out. |
The main feasibility question regarding implementation relates to the definition of focusable. The rest all seems feasible once we flesh out the details. Regardless, I'd be happy to discuss this in a deep dive meeting if we can make the time zones play ball. |
Thanks, that would help a lot for all of us to be on the same page. Here are some possible dates and times for us to do this. I apologize in advance, this is California Pacific time where I live because I'm not sure of the time zones of everyone involved. Thursday October 27: 4:00-5:00 PM PST. Everyone in the WG is welcome, though these are the specific participants that I will need to attend for this to be productive. Can all of you please confirm which dates will work for your schedule? |
Per Meeting Zone A Thursday at 4:00 PM PST works out to be 6:00 PM CST, 7:00 PM for EST, and Friday 10 AM in Australia. |
Awesome thanks! @jcsteh , @aleventhal , @cookiecrook , @scottaohara This Thursday, for example, works great for me. (hint hint...) ;) |
All of those dates work for me at this stage. Just to clarify (largely as a note to self), it's 9AM Brisbane/Queensland time, since Queensland doesn't have DST but NSW/Vic do because silly reasons. |
nov 4 or the 10th are fine by me |
Hi @jcsteh |
That time works for me. Thanks. |
This was discussed in a deep dive: https://www.w3.org/2022/11/03-aria-dive-minutes |
During the deep dive call, I said I'd provide a summary of my proposal. Looking back at all the comments in this issue, I think my proposal is simply to take the original proposal made by @accdc in #1821 (comment) except for the focusable part. That is, we add traversable: always and traversable: never, but not traversable: focusable. Because we're only applying this to recursive traversal (2H), whether the element is focusable shouldn't be relevant. Is there any reason this is problematic? I couldn't establish one on the call. Of course, there's still a lot to debate as to which roles are traversable. I acknowledge the article inside link example, but making article traversable feels kinda nasty given that an article potentially suggests a great deal of content. Separately, we probably do need a concept for roles which calculate name from content when they're focusable, but don't do this when not focusable. Chromium has this concept as noted in #1821 (comment), but Gecko currently doesn't. I'm not sure about WebKit. In any case, I think this should be handled separately from recursive traversal. I also said I'd dig into the situation with group, which is listed as a role that Gecko traverses recursively but has a specific exception for treeitems. Group was added as a recursively traversable role in https://bugzilla.mozilla.org/show_bug.cgi?id=1616851 because Gmail messages are a cell containing a tbody with display: block which gets mapped to the group role (since it's a row group). That tbody contains details about the sender, etc., so it needed to be included. However, it looks like something in the markup or Gecko has changed there and there doesn't seem to be an intervening group any more, so maybe we can remove that anyway. |
Okay. Over a year late - I'm really sorry - but better late than never I guess. 😳 As requested, I've taken a first stab at drafting these lists. I considered various parts of the spec and what browsers are currently doing, and garnished it with a bit of my own opinion. :) I was only able to look at Gecko and Chromium, so WebKit is missing from this analysis.
Gecko and Chromium currently disagree on a few of these:
|
Looking at the code comment I wrote, and the date of the commit, there's a good chance the reason was to get AccName 1.1 to rec and we had a failing test case in Gecko. 😄 (Though my code comment mentions an example that I don't see in the spec, even in version 1.1.) 🤷♀️ That said, if an author put a And that said, I don't have a strong opinion on this. |
Discussed in today's meeting: https://www.w3.org/2024/02/01-aria-minutes.html#t06 |
the worry that I have with the 'never traverse' list, as i understand it, is that this wouldn't solve the recurring problem that keeps coming up with valid html (note: valid html doesn't mean it's necessarily 'good') :
in that example the link has no name because the article has no name, even though the article has content that could be used as the name. It seems to me that for scenarios like this, if an element (which honestly might be limited to hyperlinks - this is where the problem keeps coming up) runs into an element like article and gets no name from it, it shouldn't stop there and not traverse into the article to get something useful. However, if the article was given a name, then i think it's fair for the name computation to stop there and not grab all the content of the article to create it's accessible name. cc @jcsteh for your thoughts and to correct me if i misunderstood what you were suggesting |
So on one hand, I grant that it's really not ideal to have no name for something that occurs in the wild. On the other hand, you could probably find examples of all sorts of inaccessible behaviour in the wild that are considered "valid HTML". In addition, we do not want to encourage this behaviour. Maybe this is a case where we need to make article-in-link part of the repair behaviour, but not considered "valid" from an a11y perspective. That is, I absolutely want a11y validators to flag this as bad behaviour. When you see this pattern, how big is the "article"? I don't like the idea of an entire article (in the true sense of the word) being shoved into the label of a link.
That already happens for everything in the "never traverse" list. |
Unfortunately the problem with links is more broad, in that according to the HTML spec you can put anything within one. E.G a layout table, landmark region, list markup, and much else, all of which breaks this computation. Devs keep doing this because according to HTML there is nothing wrong with it according to validators. As a possible workaround, would it be of benefit if we added an exception for link, where, if a name is not returned using the regular algorithm, it will attempt to traverse all children regardless of role to return any contained textual content as a failsafe? |
IMO, we still shouldn't consider this valid. It's a bad pattern, valid HTML or not, and it hurts users; it's hard to say whether an unnamed link or a link with a 500000 character label is worse. We can call it repair, fine, but IMO, it should still be flagged as invalid by a11y validators/checkers. But I'm one voice and I understand there is complexity here. I'm not going to push any further if the consensus is to make a "valid" exception for this case, as much as I might cringe about it. :) |
@jcsteh: There may also be elements in the link that provide a very short AccName and should be valid, and yet do not work, i.e. links with blockquote or figure have no AccName. I think that "never traverse" should not occur for any element or role. I have nothing against setting a maximum AccName length and then simply truncating the text afterwards |
At that point, we're just always traversing everything. Are you suggesting that it's reasonable to traverse a listbox if it happens to be a descendant of a name from: contents target? Consider:
I don't think it's at all reasonable for the cell to have the name "a b ... several thousand more options ..." |
Fair enough; I forgot listbox was covered by that rule. What if it were role="tree" with 10000 treeitems? |
In the case of role=tree the same would be true, only the selected treeitem is valid as the returned option for the widget. All of these are moot points though, since a selectable listbox or a tree should not be embedded in a link. We shouldn't be endorsing embedded widgets within active elements. If we do allow full traversal within a link, it should only apply to static container elements that are not interactive widgets with selectable options. |
@scottaohara I tested you example (extended and with or without aria-label on the link with Chrome and JAWS / NVDA. The more dangerous situation is, when a dev puts an aria-label on such a link: in this case he/she hides all the content of the article from screen reader user. Without an aria-label it would be quite OK, if screen readers would optimize their link handling - e.g. only saying link start on the beginning and link end on the end of the whole contents. At the time NVDA shows in Braille and reads the content well with all the set structure. JAWS puts all paragraphs of text in Braille on one line - I find it ungly. |
yes, screen readers can handle this differently though, and do seem to be working around that the hyperlink has no name, but they are exposing something anyway. Which... unfortunately, is not something I believe we can consistently bank on always working. |
For future Deep Dive planning, please include @twilco and me. |
Assigning @scottaohara who graciously agreed to write up a summary and change suggestion. |
As @cookiecrook just wrote above, we briefly discussed this in the ARIA working group last week: https://www.w3.org/2024/02/08-aria-minutes#t04 After @cookiecrook and @scottaohara write up a summary, I'll schedule a deep dive. |
Summary: This is both something that is necessary to maintain, but has caused some issues to arise - particularly do to hyperlinks, as in HTML hyperlinks have a transparent content model. What this means is that a hyperlink can wrap an element/role that doesnt' allow for the accName algorithm to traverse its contents. Hence hyperlinks can return as having no name if their only immediate child elemnet is something like an unnamed article, figure, table, aside, etc. - each of these elements only receiving their name if one has been explicitly provided by an author. When this issue was discussed in the past, this did result in instances of hyperlinks (this issue really mostly occurs becaues of hyperlinks, i can't think of another instance where this is actually an issue / isn't also an author validation error) returning no names when accessed by AT. However, recent testing shows that even though some browsers, such as Chromium-based browers, indicate that such hyperlinks have no name in their accessibility tree, browsers and/or AT are clearly working around this, and can still expose this unmamed link's content. Proposal: Note that innertext may be used by AT to compute a name for an element which otherwise the browser has returned no name for. By noting this allowance, it both helps acknowledge what some browsers and screen readers are already doing. E.g., Chromium returns an empty accessible name for the hyperlink that contains an unnamed article example, but JAWS and NVDA still expose the content of the hyperlink anyway. If we do this rather than making a normative change to accName, then we do not run the risks of ballooning performance for these potentially recursive name calculations, nor do we potentially change/break current behavior that people (users and AT developers) might be currently relying on. Additionally, by adding this note to the spec, we can resolve this issue as - at least presently - a 'wont fix', and mitigate future issues from being logged where we have to refer back to unresolved github threads to figure out what we had previously discussed, decided, but did not officially resolve on. |
Thanks for the summary. I think there's an additional concern here, though, which is that the spec doesn't specify which elements can be recursively traversed, even where they don't permit name from content. For example, unless I'm missing something, it's not clear that the button in the following example should have the label "test", rather than having an empty name:
The |
@jcsteh I think in the sub case, at least for Chrome, we just count that as "can contribute to ancestor names", whereas article is, dont use for either the ancestor or self case. Anyway, what do you propose so that we move forward with something? @scottaohara at first I thought you meant a UA repair, via element.innerText, but now I realize you mean it's an AT repair. Just a point of clarification. The "inner text" may not mean exactly the same thing to everyone, e.g. does it include alt text. |
@aleventhal is "can contribute to ancestor names" defined anywhere? Could we put that definition in the spec and use it as the basis to specify which elements can be traversed recursively as @jcsteh suggests? |
We discussed this today in the ARIA meeting, and we still don't have agreement. I'll try to summarize my thoughts. I believe button is not really an issue and should stay as is. Button, unlike link, is children presentational, so it always flattens whatever is in it and I don't believe it ever takes into account what roles are included because of this. Whatever change we decide, I think limiting it to link would be the safest option. I personally don't mind Scott's proposal as a last ditch fallback when nothing is returned for the name of a link, to use the inner textual content instead, even though this feels hacky from an algorithm perspective. Stepping back for a moment, the only place this issue really occurs is when traversing the contents of a link, and only when an element is encountered that does not support name from content. With this in mind, what do you think of the following logic when traversing the children of a link? If the ancestor element of the current node is a link, It seems to me that this would address the parsing of embedded constructs like tables, lists, figures, and all other static elements that don't support name from content while also honoring an actual label if an author deliberately sets one. |
I don't think it's ever been defined, it's just something that browsers do.
Otherwise, for example, a tree item would contactate all of the names from
child tree items into itself, when they're inside a child group.
…On Thu, Feb 22, 2024 at 4:12 PM Cynthia Shelly ***@***.***> wrote:
@aleventhal <https://github.com/aleventhal> is "can contribute to
ancestor names" defined anywhere? Could we put that definition in the spec
and use it as the basis to specify which elements can be traversed
recursively as @jcsteh <https://github.com/jcsteh> suggests?
—
Reply to this email directly, view it on GitHub
<#1821 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAKQAZWIIGXCJLBVNWVLBRDYU6YDJAVCNFSM6AAAAAAQ5AJNCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNRQGMZDCNZZGE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
All I'm suggesting is that we formalise that in the spec, which I understood to be one of the goals of this proposal in the first place and what my lists above attempt to do. |
Minutes from last weeks meeting: https://www.w3.org/2024/02/22-aria-minutes#t05 |
As we spoke of during the last ARIA meeting, there needs to be a way of defining synchronicity between the ARIA spec and the AccName spec regarding which roles are recursively traversed.
Since the time when this topic was first discussed, reference
https://lists.w3.org/Archives/Public/public-aria/2017Jun/0057.html
This level of definition was never added to the ARIA spec, even though browsers such as Chrome and others already have logic for this built into their AccName implementations.
As a result of this, it was exceedingly difficult to find a way of adding this to the AccName spec because there was no supported grouping mechanism within the ARIA spec to validate implementation. Unofficially, whether or not a role supported “name from content” was referenced instead for this logic within the ARIA spec within step 2H by referring back to step 2F, but this has led to additional confusion because there are times when roles must be traversed even if they don’t support name from content, and there is no way of definitively saying it should be one way or another given the lack of definition within the ARIA spec. This leads to additional disagreement and makes it impossible to achieve interoperability, which is what the specs strive to achieve.
Since the current grouping mechanism of whether or not a role supports “name from content” is not sufficient for this purpose, a new mechanism needs to be added that can provide this additional level of specificity. This will make it possible to easily add logic to the AccName algorithm to refer back to this grouping mechanism within the ARIA spec to identify which role should or should not be traversed and under which circumstances.
Currently, at the end of each role section in the ARIA spec is a table that defines whether that role supports “name from content”.
I propose to add a new row to that same table that defines whether the role is “Traversable”.
Traversable would support 3 values, “Always”, “Never”, and “When Focusable”.
The word “Traversable” would need to be added to the Terms list within the ARIA spec to specify its purpose. E.G. To specify whether or not the content of a role is traversable within the AccName computation and under which circumstances. (Or whatever…)
These three values (Always, Never, and When Focusable) match the functional criteria that is built into the browsers based on prior agreements when this was discussed in the past.
The meanings of Always and Never are clear in context, though it is important to note that the value When Focusable refers to the circumstance when either the role or one of its ancestor elements is focusable. This definition is not the same as saying that the role is traversable only when the role receives focus. This definition is meant to define that it will be traversable in all cases when the role or one of its ancestor elements is focusable regardless where focus resides.
Officially defining these within the ARIA spec will remove any ambiguity and ensure future interoperability as each spec evolves.
The following role list mostly matches what was originally discussed for this purpose, which includes updates to the ARIA spec and relevant guidance since then. It can be modified as needed to ensure agreement between implementors.
Always Traverse
button, checkbox, heading, link, menuitem, menuitemcheckbox, menuitemradio, option, radio, slider, switch, tab, tooltip, treeitem
Never Traverse
alert, alertdialog, application, article, banner, complementary, dialog, document, feed, figure, form, grid, img, listbox, log, main, marquee, math, menu, menubar, navigation, radiogroup, region, search, searchbox, separator, tablist, tabpanel, textbox, timer, toolbar, tree, treegrid
Traverse Only When Focusable
cell, columnheader, combobox, gridcell, contentinfo, definition, directory, group, list, note, row, rowgroup, rowheader, scrollbar, spinbutton, status, table, term
As noted, the above lists are not set in stone and we can hammer out which ones we can all agree on. (I may have overlooked a role so please suggest where to add if so.)
After this is added to the ARIA spec, it will then be possible to add a relatively simple step to the AccName algorithm to handle cases of whether or not a role is traversable and refer back to whether it is either “Always”, “Never”, or only “When Focusable”.
Feedback is welcome.
All the best,
Bryan
The text was updated successfully, but these errors were encountered: