Skip to content

Commit 82687e7

Browse files
authored
fix(AnalyticalTable): announce select-all cell for screen readers (#6408)
Fixes #6209
1 parent 3b311a2 commit 82687e7

File tree

6 files changed

+41
-12
lines changed

6 files changed

+41
-12
lines changed

packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -2455,7 +2455,13 @@ describe('AnalyticalTable', () => {
24552455
cy.get('[data-visible-column-index="0"][data-visible-row-index="0"]')
24562456
.as('selAll')
24572457
.should('have.attr', 'title', 'Select All')
2458+
.and('have.attr', 'aria-label', 'To select all rows, press the spacebar.')
24582459
.click();
2460+
2461+
cy.get('@selAll').should('have.text', 'Select All');
2462+
cy.get('@selAll').contains('Select All').should('not.be.visible');
2463+
cy.get('@selAll').should('have.attr', 'aria-label', 'To deselect all rows, press the spacebar.');
2464+
24592465
cy.get('@selectSpy').should('have.been.calledOnce');
24602466
cy.get('@selAll').should('have.attr', 'title', 'Deselect All');
24612467
cy.findByTestId('payload').should(

packages/main/src/components/AnalyticalTable/hooks/useA11y.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const setHeaderProps = (
7373
headerProps,
7474
{ column, instance }: { column: TableInstance['column']; instance: TableInstance }
7575
) => {
76-
const { translatableTexts } = instance.webComponentsReactProperties;
76+
const { translatableTexts, selectionMode } = instance.webComponentsReactProperties;
7777

7878
if (!column) {
7979
return headerProps;
@@ -82,6 +82,7 @@ const setHeaderProps = (
8282

8383
const updatedProps = {};
8484
updatedProps['aria-label'] = column.headerLabel ??= '';
85+
8586
if (updatedProps['aria-label']) {
8687
updatedProps['aria-label'] += ' ';
8788
}
@@ -100,6 +101,12 @@ const setHeaderProps = (
100101
}
101102
}
102103

104+
if (selectionMode === AnalyticalTableSelectionMode.Multiple && column.id === '__ui5wcr__internal_selection_column') {
105+
updatedProps['aria-label'] += instance.isAllRowsSelected
106+
? translatableTexts.deselectAllA11yText
107+
: translatableTexts.selectAllA11yText;
108+
}
109+
103110
return [headerProps, { isFiltered, ...updatedProps }];
104111
};
105112

packages/main/src/components/AnalyticalTable/hooks/useRowSelectionColumn.tsx

+12-9
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,25 @@ const customCheckBoxStyling = {
1717
const Header = (instance: TableInstance) => {
1818
const {
1919
getToggleAllRowsSelectedProps,
20-
webComponentsReactProperties: { selectionMode }
20+
webComponentsReactProperties: { selectionMode, translatableTexts, classes }
2121
} = instance;
2222

2323
if (selectionMode === AnalyticalTableSelectionMode.Single) {
2424
return null;
2525
}
2626
const checkBoxProps = getToggleAllRowsSelectedProps();
2727
return (
28-
<CheckBox
29-
{...checkBoxProps}
30-
style={customCheckBoxStyling}
31-
tabIndex={-1}
32-
onChange={undefined}
33-
checked={checkBoxProps.indeterminate ? true : checkBoxProps.checked}
34-
aria-hidden="true"
35-
/>
28+
<>
29+
<CheckBox
30+
{...checkBoxProps}
31+
style={customCheckBoxStyling}
32+
tabIndex={-1}
33+
onChange={undefined}
34+
checked={checkBoxProps.indeterminate ? true : checkBoxProps.checked}
35+
aria-hidden="true"
36+
/>
37+
<span className={classes.hiddenA11yText}>{translatableTexts.selectAllText}</span>
38+
</>
3639
);
3740
};
3841

packages/main/src/components/AnalyticalTable/index.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ import {
4444
NO_DATA_FILTERED,
4545
SELECT_ALL,
4646
SELECT_PRESS_SPACE,
47-
UNSELECT_PRESS_SPACE
47+
UNSELECT_PRESS_SPACE,
48+
SELECT_ALL_PRESS_SPACE,
49+
UNSELECT_ALL_PRESS_SPACE
4850
} from '../../i18n/i18n-defaults.js';
4951
import { BusyIndicator } from '../../webComponents/BusyIndicator/index.js';
5052
import { Text } from '../../webComponents/Text/index.js';
@@ -202,7 +204,9 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
202204
expandNodeA11yText: i18nBundle.getText(EXPAND_NODE),
203205
collapseNodeA11yText: i18nBundle.getText(COLLAPSE_NODE),
204206
filteredA11yText: i18nBundle.getText(FILTERED),
205-
groupedA11yText: i18nBundle.getText(GROUPED)
207+
groupedA11yText: i18nBundle.getText(GROUPED),
208+
selectAllA11yText: i18nBundle.getText(SELECT_ALL_PRESS_SPACE),
209+
deselectAllA11yText: i18nBundle.getText(UNSELECT_ALL_PRESS_SPACE)
206210
},
207211
tagNamesWhichShouldNotSelectARow,
208212
tableRef,
@@ -740,6 +744,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
740744
aria-rowcount={rows.length}
741745
aria-colcount={visibleColumns.length}
742746
data-per-page={internalVisibleRowCount}
747+
aria-multiselectable={selectionMode === AnalyticalTableSelectionMode.Multiple}
743748
data-component-name="AnalyticalTableContainer"
744749
ref={tableRef}
745750
className={tableClasses}

packages/main/src/components/AnalyticalTable/types/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ export interface WCRPropertiesType {
172172
collapseNodeA11yText: string;
173173
filteredA11yText: string;
174174
groupedA11yText: string;
175+
selectAllA11yText: string;
176+
deselectAllA11yText: string;
175177
};
176178
tagNamesWhichShouldNotSelectARow: Set<string>;
177179
tableRef: MutableRefObject<DivWithCustomScrollProp>;

packages/main/src/i18n/messagebundle.properties

+6
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ SELECT_PRESS_SPACE=To select the row, press the spacebar
252252
#XACT: Aria label text for selectable table cells in selected state
253253
UNSELECT_PRESS_SPACE=To deselect the row, press the spacebar
254254

255+
#XACT: Aria label for unselected select-all checkbox cell inside a table
256+
SELECT_ALL_PRESS_SPACE=To select all rows, press the spacebar.
257+
258+
#XACT: Aria label for selected select-all checkbox cell inside a table
259+
UNSELECT_ALL_PRESS_SPACE=To deselect all rows, press the spacebar.
260+
255261
#XACT: Aria label text for an invalid table with overlay
256262
INVALID_TABLE=Invalid Table
257263

0 commit comments

Comments
 (0)