Repository navigation
feat: add HasAriaDescription interface - #25117
Conversation
Adds a mixin interface for setting the accessible description of a component via the aria-description and aria-describedby attributes, following the HasAriaLabel pattern. The aria-describedby value can also be set by referencing another component, generating an id for it lazily when needed. Unlike HasAriaLabel, the getters return the plain attribute value or null instead of Optional, as no obvious reason was found to support Optional. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aria-describedby also works with hidden elements, so the guidance to choose between the attributes based on visibility was misleading. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| * | ||
| * @return the aria-description or {@code null} if none has been set | ||
| */ | ||
| default String getAriaDescription() { |
There was a problem hiding this comment.
The getters return the plain attribute value or null, which diverges from the Optional<String> getters in HasAriaLabel. Why Optional was chosen there isn't obvious to me.
There was a problem hiding this comment.
I don't have strong opinions on that, but it is definitely weird to have a different return type for a similar use case.
There was a problem hiding this comment.
OK, changed the getters to return Optional.
| } | ||
| ComponentUtil.resolveOrGenerateIdLater(getElement(), | ||
| descriptionComponent, "ariadescribedby-", | ||
| this::setAriaDescribedBy); |
There was a problem hiding this comment.
The utility class takes a Consumer<String> that is actually wrong, since the instance is then captured by other lambdas stored in the VaadinSession.
This should be fixed in ComponentUtil.resolveOrGenerateIdLater, maybe in a separated PR.
| ComponentUtil.resolveOrGenerateIdLater(getElement(), | ||
| descriptionComponent, "ariadescribedby-", | ||
| this::setAriaDescribedBy); |
There was a problem hiding this comment.
If I call this method and then call setAriaDescribedBy(String), the former will anyway override the latter, because the beforeClientResponse gets not cancelled.
I guess this is a general issue for all components using the ComponentUtil.resolveOrGenerateIdLater method.
There was a problem hiding this comment.
Right. I guess we could also sidestep this by setting aria-describedby inside a beforeClientResponse callback, but I'm not sure deferring all the work to these callbacks is a good approach in general.
There was a problem hiding this comment.
Let's keep this also in a separate PR (#25119)
There was a problem hiding this comment.
I'd appreciate it if this one could be merged first, so I can continue working on the Flow components.
Aligns the getters with the Optional<String> return type used by HasAriaLabel. Also adds a test for setting the description component id after calling setAriaDescribedBy(Component) and switches the test class to qualified Assertions calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Addresses review feedback asking for attribute purpose references at the class level. The class javadoc now explains the accessibility purpose and links the setter methods, while attribute names and spec links stay in the method javadocs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Asking for a friend.. if no component supports setAriaDescription - why was it added in the first place? Wouldn't it be more sane to have two interfaces, one for HasAriaDescription and one for HasAriaDescribedBy so that the fields only implement the later (which they clearly support?) |
Huh, that's actually a good point... I think I'm going to open a PR :) thanks! |
On the other hand, these two methods really go hand in hand, and they even interact: one of them can end up shadowing the other. Also, field components could technically support aria-description by creating an invisible node with that text and pointing to it via aria-describedby. It's just out of scope for now. I'll discuss this with the team. |
Removes setAriaDescription(String) and getAriaDescription() from the HasAriaDescription interface (added in #25117, unreleased) because assistive technology support for the aria-description attribute is still not ideal. The API can be reconsidered later once support improves. Also removes the now-unused ARIA_DESCRIPTION_ATTRIBUTE_NAME constant from ElementConstants. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
I discussed this with the team, and we decided to drop |
|
Thanks for checking with the team! |
…#25135) ## Description Removes `setAriaDescription(String)` and `getAriaDescription()` from the `HasAriaDescription` interface (added in vaadin#25117, unreleased) because assistive technology support for the `aria-description` attribute is still not ideal. The API can be reconsidered later once support improves. Part of vaadin/web-components#11975 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
This ticket/PR has been released with Vaadin 25.3.0-alpha8. |
## Summary Vaadin 25.3 added two accessibility mixin interfaces that the *Mixin Interfaces* page doesn't list, even though that list is where a reader looks for what a component can implement: - `vaadin/flow#24782` — `HasAriaRole` (`setAriaRole()` / `getAriaRole()`) - `vaadin/flow#25117`, narrowed by `vaadin/flow#25135` — `HasAriaDescription` (`setAriaDescribedBy(String)`, `setAriaDescribedBy(Component)`, `getAriaDescribedBy()`) ## What changed In `articles/flow/component-internals/mixins.adoc`, under *Other Useful Mixin Interfaces*: - added `HasAriaDescription` — the accessible description is set by referencing existing elements with `setAriaDescribedBy()`, and supplements the accessible name - added `HasAriaRole` — sets the `role` attribute on the root element by default, and the methods can be overridden to target another element - fixed the name of `HasAriaLabel`, which the same list spelled `HasArialLabel` (the only occurrence in the docs) ## How to test Documentation only, no code examples added, so nothing to compile. The descriptions match the javadoc of `HasAriaRole` and `HasAriaDescription` in 25.3. Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>



Description
Adds a
HasAriaDescriptionmixin interface for setting the accessible description of a component, following theHasAriaLabelpattern:setAriaDescription(String)/getAriaDescription()for thearia-descriptionattributesetAriaDescribedBy(String)/getAriaDescribedBy()for thearia-describedbyattributesetAriaDescribedBy(Component)for referencing a description component directly, generating an id for it lazily when needed (same mechanism assetAriaLabelledBy(Component))Also adds the
aria-descriptionandaria-describedbyattribute name constants toElementConstants.Part of vaadin/web-components#11975
Type of change