react-bootstrap icon indicating copy to clipboard operation
react-bootstrap copied to clipboard

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

Open catamphetamine opened this issue 3 years ago • 4 comments

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: https://github.com/react-restart/ui/issues/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 avatar Feb 17 '22 07:02 catamphetamine

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 avatar Feb 17 '22 07:02 catamphetamine

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".

catamphetamine avatar Feb 17 '22 07:02 catamphetamine

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 avatar Oct 14 '23 17:10 imageck

Potential dupe of #4204

imageck avatar Oct 14 '23 17:10 imageck