web-components
web-components copied to clipboard
Grid i18n API
What is the problem?
Currently multiple values inside the grid are hard coded and can't be changed; this is needed for a full translated-able app.
Examples:
https://github.com/vaadin/web-components/blob/61076cbbde90b7689c8754a0e673ee86e32f219f/packages/grid/src/vaadin-grid-selection-column.js#L139
https://github.com/vaadin/web-components/blob/61076cbbde90b7689c8754a0e673ee86e32f219f/packages/grid/src/vaadin-grid-selection-column.js#L161
^There has to be a way to also add e.g. a suffix or postfix to this value like Select Row name_of_person_in_there.
Sort by {columnHeader} (couldn't find it)
https://github.com/vaadin/flow-components/blob/d438db26433aa5651c5a6656f12405e0864a5125/vaadin-grid-flow-parent/vaadin-grid-flow/src/main/java/com/vaadin/flow/component/grid/AbstractColumn.java#L244
Browsers
- [x] Chrome
- [x] Firefox
- [x] Safari
- [x] Safari on iOS
- [x] Edge
Screen Readers
- [ ] None
- [x] NVDA
- [x] JAWS
- [x] VoiceOver on MacOS
- [x] VoiceOver on iOS
@rolfsmeds This was today on the list of the tester's findings. I would argue that this is not an enhancement and instead a bug.
From the a11y point of view it's definitely a bug. However, it requires adding new API so we marked it as enhancement.
shameless push - I've read something in discord about a11y time 😗
Thanks for reminding about this! We are going to have a meeting early next week to discuss the accessibility project scope.
Our Testers discovered there is a little more to this problem: Depending on Grids focus mode, the screenreader doesn't tell you any details regarding these chechboxes in the "Select All" column.
Edge with NVDA at https://vaadin.com/docs/latest/components/grid#multi-select-mode
(Just for clarification: The first person in the grid actually has the first name "Aria".)
NVDA: "Select All column header row 1 Select All column 1"
@knoobie opened this issue, because there is no way to localize these "Select All"s.
Press ENTER.
NVDA: "clickable check box not checked"
That's bad. No context what this checkbox is for.
NVDA: "Select Row not selected row 2 Select All column 1"
That could be improved:
- Column name "Select All" is suboptimal. It only suits the actual "Select All" checkbox in the header. Maybe "Selection" column would be better.
- It would be helpful to "name the row" somehow. I.e. what content is in this row. In this example "-Last Name-, -First Name-" would be helpful. I guess, my proposal is, developer should be able to provide some kind of ValueProdiver which adds context to the "Select Row" checkbox.
Press ENTER.
NVDA: "clickable check box not checked"
Well, same as above: No context what this checkbox is for.
Thanks @AndreasSamjeske, this indeed also needs to be addressed.
We added support for marking columns as "row headers" with rowHeader property in the WC and setRowHeader(true) in Flow and (which renders their cells as <th scope="row">) in V24.2. This should at least improve announcements of the cell itself, but the checkbox should also have an aria-label that clarifies what it does. I think it would make sense to concatenate the content of "row header" cells on the row as the aria-label.
One of our customers criticized these not localized texts "Select all" and "Sort by ..." in grids. Is there any timetable for this issue?
Unfortunately not at the moment. We do fully intend to address it, we just can't say anything about when at this point.
The main factor affecting this feature is the planned "unified i18n" for components to replace the rather awkward i18n objects currently used.
We were hoping to get that feature in place so that we could make these strings localizable without introducing an i18n object API for Grid. We expected to have that in place by now, but unfortunately had to de-prioritize it.
Thanx for providing some insight. Unfortunately our customer demands a solution. Is there any viable workaround, like overriding these values hard-coded on our side?
Does @web-padawan have any ideas? Otherwise I suppose we should try to squeeze it into our backlog for V24.6.
I think this should be possible by updating vaadin-grid-sorter elements as they should only be rendered once:
grid.querySelectorAll('vaadin-grid-sorter').forEach((sorter) => {
sorter.setAttribute('aria-label', 'Sort by ...');
});
To get the reference to "select all" checkbox, it's enough to use CSS class name:
const checkbox = grid.querySelector('.vaadin-grid-select-all-checkbox');
Note, when using Flow component this should be done on attach (e.g. detaching and reattaching the grid will create a new instance of the web component and you would need to make sure the JS is executed again to update aria-label).
onAttach seems to fire too early: executed JS couldn't find sorter in header cells. So we came up with this:
String javascriptObserver =
"""
const observer = new MutationObserver((mutations, observer) =>
{
if (this.querySelectorAll('vaadin-grid-sorter'))
{
this.querySelectorAll('vaadin-grid-sorter').forEach((sorter) =>
{
var columnName = sorter.getAttribute('aria-label').replace('Sort by', '');
var newLabel = $0 + columnName + ' ' + $1;
sorter.setAttribute('aria-label', newLabel);
});
observer.disconnect();
}
});
observer.observe(this, {
childList: true,
subtree: true
});
""";
String ariaLabelPrefix = localizer.localize("vaadinGridSorterAriaLabelPrefix");
String ariaLabelSuffix = localizer.localize("vaadinGridSorterAriaLabelSuffix");
baseGrid.getElement().executeJs(javascriptObserver, ariaLabelPrefix, ariaLabelSuffix);
Here are the updated locations of hardcoded strings mentioned in the issue:
<vaadin-grid-selection-column>
Currently located in the mixin shared by both web component and Flow version:
https://github.com/vaadin/web-components/blob/9548842becbe3a0aa79fc8653de8f1eddf3c657d/packages/grid/src/vaadin-grid-selection-column-base-mixin.js#L177
https://github.com/vaadin/web-components/blob/9548842becbe3a0aa79fc8653de8f1eddf3c657d/packages/grid/src/vaadin-grid-selection-column-base-mixin.js#L156
<vaadin-grid-sorter>
Flow counterpart "Sort by" is currently hardcoded in the grid connector.
Web component has no API but it would need one to cover the hardcoded string in vaadin-crud:
https://github.com/vaadin/web-components/blob/9548842becbe3a0aa79fc8653de8f1eddf3c657d/packages/crud/src/vaadin-crud-grid-mixin.js#L188
Note: as vaadin-grid-sort-column also creates vaadin-grid-sorter internally, it would presumably need the same API as the one that we might add API add for configuring vaadin-grid-sorter (unless we add it on vaadin-grid itself).
For the record, in case of vaadin-crud we also have vaadin-grid-filter which could benefit from the same approach:
https://github.com/vaadin/web-components/blob/9548842becbe3a0aa79fc8653de8f1eddf3c657d/packages/crud/src/vaadin-crud-grid-mixin.js#L196
IMO these cases could be handled separately, so maybe we should create two separate issues for the actual implementation and keep this one as an "epic".
Some ideas regarding the actual API. I think for sorter / sort column we could use any of those:
- Use
accessibleNameproperty as we do in other components includingvaadin-griditself, - Use
ariaLabelproperty on the sorter that would reflect to attribute like in e.g.vaadin-drawer-toggle.
Personally I like the first approach more since it would also be more suitable for vaadin-grid-sort-column and it would make it possible to e.g. make some changes to the sorter DOM structure while using the same API.
As for vaadin-grid-selection-column, we could use something similar to itemAccessibleNameGenerator recently added to virtual list for configuring "Select row" if we want to add value provider etc on the Flow side. Then we would name a simple property for "Select all" checkbox, could be something like these:
selectRowCheckboxAccessibleNameGeneratorORselectRowAccessibleNameGeneratorselectAllCheckboxAccessibleNameORselectAllAccessibleName
While we're at it, we could add accessible names to places that currently don't even have hardcoded ones, like the empty selection column header cell when the select-all checkbox is not available.
There's also the edge case discovered by a tester who noted that in a lazy loading Grid, the select all checkbox is absent and nothing is announced there; it should be possible to set a localizable text in the Grid's configuration there. There's a workaround where you can set a pseudo-element with CSS:
vaadin-grid vaadin-grid-cell-content:has(vaadin-checkbox#selectAllCheckbox[hidden])::after {
content: "" / "Select all rows";
}
but this isn't localizable easily.