Skip to content
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

Feature: <Dropdown.Menu/> custom aria-labelledby property #6249

Open
catamphetamine opened this issue Feb 17, 2022 · 4 comments
Open

Feature: <Dropdown.Menu/> custom aria-labelledby property #6249

catamphetamine opened this issue Feb 17, 2022 · 4 comments

Comments

@catamphetamine
Copy link

catamphetamine commented Feb 17, 2022

Is your feature request related to a problem? Please describe

Currently, <Dropdown.Menu/> component doesn't accept a custom aria-labelledby property.

The properties generated by @restart/ui useDropdownMenu() hook overwrite any custom-passsed aria-labelledby property with a toggler element id which is not correct:
react-restart/ui#50

Describe the solution you'd like

The solution would be @restart/ui adding an opt-out flag or something.
Or maybe <Dropdown.Menu/> component re-applying a custom aria-labelledby property over the one generated by @restart/ui useDropdownMenu() hook.

Describe alternatives you've considered

No response

Additional context

No response

@catamphetamine
Copy link
Author

catamphetamine commented Feb 17, 2022

On the other hand, I can see how it could work with a "recursive" aria-labelledby:

image

<label id="label-1"/>
<div class="dropdown">
  <button id="react-aria-2" aria-labelledby="label-1">Green</button>
  <div aria-labelledby="react-aria-2">...</div>
</div>

If a screen reader supports recursive aria-labelledby, then it would most likely resolve stuff correctly.

Except they say screen readers don't resolve aria-labelledby recursively:

Quote:

The role of aria-labelledby in the naming calculation is very important to understand, because aria-labelledby is only processed once and is not recursive.

A simple demonstration of this is as follows:

<input id="my_name" aria-labelledby="my_name" aria-label="Your name is?" type="text" />
Which results in the Name “Your name is?”.

The reason being, the algorithm first checks for the presence of aria-labelledby, finds it, then follows the referenced ID to the element, and then applies the same naming algorithm to the referenced element while ignoring all additional instances of aria-labelledby. This is necessary to prevent infinite loops from occurring within browsers that may crash both browsers and assistive technologies.

This logic also allows the algorithm to handle more complex naming calculations, such as the following:

<div id="parentId" >
  <button aria-labelledby="parentId" aria-label="Remove event:" > X </button>
  <span class="event"> Blindfolded Dart Throwing Contest </span>
</div>

Which results in the button Name “Remove event: Blindfolded Dart Throwing Contest”, because the algorithm detects the presence of aria-labelledby on the button, follows that to the referenced element, then applies the same algorithm to that element and all of its child elements while ignoring any further instances of aria-labelledby.

Source: https://www.levelaccess.com/how-the-w3c-text-alternative-computation-works/

@catamphetamine
Copy link
Author

Tested in NVDA: it doesn't resolve aria-labelledby recursively.
So it says: "List Green" (instead of "List Color"), then "List Green. Green List Green 2 of 3".

@imageck
Copy link
Contributor

imageck commented Oct 14, 2023

Have you tried creating a custom component and using it with as? All the relevant props will be passed to it including aria-labelledby.

@imageck
Copy link
Contributor

imageck commented Oct 14, 2023

Potential dupe of #4204

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants