aria icon indicating copy to clipboard operation
aria copied to clipboard

Spec for menu/menuitem does not provide enough author guidance for structure

Open aleventhal opened this issue 1 year ago • 12 comments

Describe your concern

UAs/ATs need a way to determine the parent menuitem that caused a menu to be opened. This is important for Talback on Android, which provides the name of the menu along with the choices.

While the spec does not provide this, somehow the ARIA Authoring Practices Guide does, which says: "If activating a menuitem opens a submenu, the menuitem is known as a parent menuitem. A submenu's menu element is:

  • Contained inside the same menu element as its parent menuitem.
  • Is the sibling element immediately following its parent menuitem."

If this is generally followed, it would allow the UA to determine which menuitem opened a given submenu, by navigating from the role="menu" object to the previous sibling in the accessible object tree.

One caveat is that this is also slightly incomplete, because it says "sibling element" instead of "sibling accessible object". Authors should also be able to use aria-owns to create these relationships. The important thing is the final tree structure, not the DOM structure.

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

https://w3c.github.io/aria/#menuitem https://w3c.github.io/aria/#menu https://www.w3.org/WAI/ARIA/apg/patterns/menubar/

Link to documentation:

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

Yes

aleventhal avatar Aug 01 '24 13:08 aleventhal

resolving this would probably help close out https://github.com/w3c/aria/issues/1711 and https://github.com/w3c/aria/issues/1120 ?

scottaohara avatar Aug 22 '24 17:08 scottaohara

Can you provide an example of a parent/child and sibling/child relationship structure? I think it might be useful for better understanding the issue (at least it would be for me).

aardrian avatar Aug 22 '24 17:08 aardrian

Discussion of edge cases and usage patterns in the WG meeting today was complex enough that perhaps we should consider defining a nesting algorithm for menus/submenus, trees, treegrids, etc. taking into account DOM tree, aria-owns, aria-controls, the image map edge case, generic in-betweener elements, and more...

cookiecrook avatar Aug 22 '24 18:08 cookiecrook

Discussed in today's meeting: https://www.w3.org/2024/08/22-aria-minutes#t09

However, the exact next steps were not clear and we ran out of time. To pick up next meeting.

spectranaut avatar Aug 22 '24 18:08 spectranaut

Regarding menus and trees, all of these should be supported equally.

<ul role="menu" style="list-style: none;" >
<li>
<a role="menuitem" aria-haspopup="true" tabindex="0" aria-expanded="true" > Branch </a>
<ul role="menu" style="list-style: none;" >
<li>
<a role="menuitem" tabindex="-1" > Leaf </a>
</li>
</ul>
</li>
</ul>
<ul role="menu" style="list-style: none;" >
<li role="menuitem" aria-haspopup="true" tabindex="0" aria-expanded="true" >
<a> Branch </a>
<ul role="menu" style="list-style: none;" >
<li role="menuitem" tabindex="-1" >
<a> Leaf </a>
</li>
</ul>
</li>
</ul>
<ul role="tree" aria-label="Name" style="list-style: none;" >
<li>
<a role="treeitem" tabindex="0" aria-expanded="true" > Branch </a>
<ul role="group" style="list-style: none;" >
<li>
<a role="treeitem" tabindex="-1" > Leaf </a>
</li>
</ul>
</li>
</ul>
<ul role="tree" aria-label="Name" style="list-style: none;" >
<li role="treeitem" tabindex="0" aria-expanded="true">
<a> Branch </a>
<ul role="group" style="list-style: none;" >
<li role="treeitem" tabindex="-1" >
<a> Leaf </a>
</li>
</ul>
</li>
</ul>

Ideally this wouldn't be dependent on list markup, but rather the role nesting structure.

accdc avatar Aug 22 '24 20:08 accdc

How about the following algorithm for finding the name of menu from a menuitem:

Starting from menuitem:

  1. Navigate to ancestor menu (up to 3 ancestors up). If none found, return the empty string.
  2. If another element controls this menu, navigate to that. If a menuitem, skip to step 4, else return the empty string.
  3. Navigate to previous sibling menu item (up to 3 previous siblings). If none found, return the empty string.
  4. If expanded, use accessible name of this menu item, else return the empty string.

aleventhal avatar Aug 23 '24 14:08 aleventhal

It does work in these scenarios, but it's very easy to break by changing the nested elements. E.G. By adding a div around the elements within the LI.

I don't know what architecture you are running, but do you have to use parent/child/sibling nodes, or can you also use a CSS selector?

E.G.

From menuitem, move to the containing role=menu, check for a parent role of role="menuitem" then process. Otherwise, from role="menu", use parentNode.querySelector('[role="menuitem"]') to get the first menuitem, check if this is the same as the originating menuitem node and ignore if so, otherwise return it's name.

Unfortunately parentNode assumes that both menuitem and menu are siblings in the same direct container, but the search would be more flexible by moving up based on role, then querying again by role.

Like I said though, this may be naive since I don't know if this is possible in your code.

accdc avatar Aug 23 '24 19:08 accdc

Updated proposal:

  1. Navigate to ancestor object with role menu. If none found, return the empty string.
  2. If the menu has an accessible name, return that
  3. If another element has a controls relationship pointing this menu, inspect that. If that object has a name, return that.
  4. Inspect the previous sibling menu item. If none found, return the empty string.
  5. If expanded, use accessible name of this menu item, else return the empty string.

aleventhal avatar Aug 29 '24 17:08 aleventhal

Adding some examples of current menu implementations that would return the wrong accName if using the ancestor menu > sibling menu item approach, based on what was discussed in the call.

I used examples from the open ui menu page, plus the current version of Fluent just because I work on it :D. I left out libraries where the examples didn't include popup menus.

  • Fluent (legacy): there are multiple intervening generics, but each menu is rendered in its own layer at the end of the DOM. The closest ancestor > sibling menu item of a second-level menu would be the last menuitem of the higher-level menu.
  • Fluent (current): same approach with layers, with the same issue.
  • Ant design: same approach as Fluent, each menu is rendered in its own layer/div at the end of the DOM, so the closest ancestor > sibling of a second-level menu would be the last menu item of the parent menu.
  • Bootstrap: doesn’t use menu roles
  • Evergreen: doesn’t have multi-level menus, but the single-level menus are rendered in their own layer at the end of the DOM. Seems likely mutli-level menus would have the same issue.
  • Lightning design: this one would work! It renders flyout menus inline in the DOM.
  • Semantic UI: renders flyouts inline in the DOM, but does not use menu roles.
  • Spectrum: renders each submenu in its own layer at the end of the DOM, so the ancestor > sibling check would always be the last menuitem of the parent menu.

TL:DR: 1 example would return the right name, 5 would not, and 2 are N/A because of the lack of menu semantics.

smhigley avatar Aug 29 '24 18:08 smhigley

Notes from yesterday's WG meeting: https://www.w3.org/2024/08/29-aria-minutes#t04

spectranaut avatar Aug 30 '24 17:08 spectranaut

Discussed again in today's meeting: https://www.w3.org/2024/09/05-aria-minutes#t05

Decision was to encourage use of aria-controls or aria-owns in menu or menuitem spec, after some more experimentation between the two options.

spectranaut avatar Sep 05 '24 18:09 spectranaut

So do we make it an author should? I would vote for aria-controls over aria-owns personally.

On Thu, Sep 5, 2024 at 2:19 PM Valerie Young @.***> wrote:

Discussed again in today's meeting: https://www.w3.org/2024/09/05-aria-minutes#t05

Decision was to encourage use of aria-controls or aria-owns in menu or menuitem spec, after some more experimentation between the two options.

— Reply to this email directly, view it on GitHub https://github.com/w3c/aria/issues/2300#issuecomment-2332369464, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKQAZWTGFZRGLHEF3WVOP3ZVCOCPAVCNFSM6AAAAABL2UJWVOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMZSGM3DSNBWGQ . You are receiving this because you authored the thread.Message ID: @.***>

aleventhal avatar Sep 12 '24 14:09 aleventhal

Next steps for this issue were discussed in today's working group meeting: https://www.w3.org/2024/11/21-aria-minutes#0bee

It seems to motivate a fix here, we would need to have more need from ATs. It seems that many screen readers don't need this fix, and it was only request from Talk Back. We are curious about other input ATs. The label "need AT input" was create and hopefully soon we will develop a process for reaching out and getting regular feedback from a wide variety of ATs (besides those represented in the ARIA working group already).

spectranaut avatar Nov 21 '24 19:11 spectranaut