ni / nimble

The NI Nimble Design System
https://nimble.ni.dev
MIT License
30 stars 8 forks source link

setting aria-label on nimble icon causes accessibility issue #1510

Closed mollykreis closed 11 months ago

mollykreis commented 12 months ago

πŸ› Bug Report

Setting an aria-label on a nimble icon causes an accessibility issue: Elements must only use allowed ARIA attributes. The role of the nimble icon is generic, and generic elements are not allowed to have an ARIA label or description.

πŸ’» Repro or Code Sample

This causes an accessibility issue any time aria-label is applied to an icon, which currently seems to be the recommended approach to making the icon accessible.

For example:

πŸ€” Expected Behavior

We should have a recommended way to set an accessible label on a nimble icon that doesn't cause its own accessibility issues

😯 Current Behavior

Our recommended way to set an accessible label on a nimble icon isn't correct because it causes accessibility issues

πŸ’ Possible Solution

πŸ”¦ Context

🌍 Your Environment

msmithNI commented 11 months ago

Currently our docs state that icons should consider setting title but don't mention aria-label specifically. The icon column cell view does set aria-label though (source link).

Based on the outcome of this issue we may need to update our docs about icon accessibility guidance:

m-akinc commented 11 months ago

I can think of three options:

  1. Expect/instruct clients to set title on icons (we already suggest this in documentation), then forward that value to the aria-label on the svg in the shadow DOM (which implicitly has role img).
  2. Introduce a new attribute (e.g. label) on icons that the clients must set, and forward that value to the aria-label on the svg in the shadow DOM.
  3. Set role="img" on the icon element, and expect clients to set aria-label on it (which seems to be our current, undocumented expectation).

I would advocate for 3 as it does not require additions to the API, nor relies on overloading the title attribute with an extra, mandatory purpose. Acording to w3c, "An img represents a single graphic within a document, whether or not it is formed by a collection of drawing objects." And MDN notes that "most screen readers will consider the element with role="img" set on it to be like a black box, and not access the individual elements inside it." Thus it seems reasonable to put the img role on an element that contains another img element within it (the svg).

m-akinc commented 11 months ago

After talking with the team, I understand that we do not want to require clients to set aria-label directly. This excludes my previously preferred approach of setting the icon's role to img. This leaves the other two options (i and ii). I looked for other existing attributes that we might forward to the svg's aria-label (like alt), but found none.

I am currently leaning toward adding a new label attribute to our icons that does nothing but get forwarded to the svg's aria-label. I prefer that to forwarding the title attribute for two reasons: (1) I don't want to force the accessible name to be the tooltip, and (2) I read some articles that discouraged the use of title in general, so I'm reluctant to promote its use. @rajsite does this seem reasonable to you?

rajsite commented 11 months ago

@m-akinc can you express more explicitly the contract you are trying to represent with icons?

If we are trying to make icons analogous to <img> then the api surface you describe is surprising to me. I don't see any discussion of what we discussed about alt as the attribute vs label.

If you are choosing a different model to represent the icon api would be helpful to discuss.

For the implementation detail of how the public api applies to the content in the shadowroot can you share what research you did on defining accessibility for inline svg elements? Found this googling: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/img_role#svg_and_roleimg

And this hints at some of the presentation behaviors you were discussing at stand-up about children of element's with role=img: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/img_role#all_descendants_are_presentational

Guessing I'm asking you to show me if it's reasonable, I haven't done the research to understand what the reasonable implementation is. Then hopefully we can capture some of that research.

m-akinc commented 11 months ago

I was looking at the <svg> element as a model for the API of the Nimble icon, since that is the element it wraps. Since <svg> doesn't have alt as part of its API, it didn't seem appropriate to provide alt on our icons. I thought it safer to introduce a new attribute/property name (i.e. label) than to adopt an existing one that might carry unintended associations/expectations. That was my line of reasoning, at least. I could be convinced otherwise.

I researched approaches to making inline SVGs accessible, and a few reputable sources recommended adding a <title> element as the first child of an <svg> element, e.g.: https://www.deque.com/blog/creating-accessible-svgs/ https://www.w3.org/TR/SVG11/struct.html#DescriptionAndTitleElements https://css-tricks.com/accessible-svgs/#aa-2-inline-svg Some sources also recommend setting aria-labelledby to point to this <title> element. However, none of these sources mentioned aria-label at all, which seems like a strange omission. It's also not clear to me if/what difference there is from setting the title attribute. As W3C says, "User agents may ... display the β€˜title’ element as a tooltip."

On the other hand, MDN clearly recommends using aria-label (or aria-labelledby).

As far as whether we should use aria-label or a <title> element, both should be easy enough to implement. The template we use for Nimble icons doesn't provide an easy way to insert a <title> element into the <svg>, but we could do this programmatically, just as we are currently forwarding the aria-label value. A better question is whether we want the user to be able to set a tooltip that is different from the accessible name of the icon. In Chrome (at least), the aria-label value takes priority over the <title> content as the accessible name.

rajsite commented 11 months ago

@m-akinc

I was looking at the element as a model for the API of the Nimble icon, since that is the element it wraps

Don't think that's particularly a strong reason in this case. For something like anchors we are trying to align as much as possible with the wrapped anchor. If that was the case (trying to expose it as an svg), the user may expect they can manipulate the contents of the svg tag which is not the case like by inserting a title tag. In this case how an icon is visualized is an implementation detail. I don't think we want to expose to users that it is an <svg> specifically. It could be implemented with something else in the future.

The mdn discussion linked: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/img_role#svg_and_roleimg

Seems to be trying very hard to make it behave like an image. So I think I'd lean to an <img> tag api surface and forward an alt to aria-label on the child svg and set a role="img" on the child svg element.