• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-webcomponents-react / 4491233783

pending completion
4491233783

Pull #4392

github

GitHub
Merge e25df06bb into 3a658107c
Pull Request #4392: fix(AnalyticalTable): announce grouped, filtered and sorted columns with screen readers

2598 of 3588 branches covered (72.41%)

23 of 24 new or added lines in 1 file covered. (95.83%)

1 existing line in 1 file now uncovered.

5062 of 5873 relevant lines covered (86.19%)

14538.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.7
/packages/main/src/components/AnalyticalTable/hooks/useA11y.ts
1
import { KeyboardEventHandler } from 'react';
2
import { AnalyticalTableSelectionBehavior, AnalyticalTableSelectionMode } from '../../../enums';
3

4
interface UpdatedCellProptypes {
5
  onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
6
  'aria-expanded'?: string | boolean;
7
  'aria-label'?: string;
8
  'aria-colindex'?: number;
9
}
10

11
const setCellProps = (cellProps, { cell: { column, row, value }, instance }) => {
369✔
12
  const columnIndex = instance.visibleColumns.findIndex(({ id }) => id === column.id);
2,474,242✔
13
  const { alwaysShowSubComponent, renderRowSubComponent, translatableTexts, selectionMode, selectionBehavior } =
14
    instance.webComponentsReactProperties;
950,938✔
15
  const updatedCellProps: UpdatedCellProptypes = { 'aria-colindex': columnIndex + 1 }; // aria index is 1 based, not 0
950,938✔
16

17
  const RowSubComponent = typeof renderRowSubComponent === 'function' ? renderRowSubComponent(row) : undefined;
950,938✔
18
  const rowIsExpandable = row.canExpand || (RowSubComponent && !alwaysShowSubComponent);
950,938✔
19

20
  const userCols = instance.visibleColumns.filter(
950,938✔
21
    ({ id }) =>
22
      id !== '__ui5wcr__internal_selection_column' &&
3,997,546✔
23
      id !== '__ui5wcr__internal_highlight_column' &&
24
      id !== '__ui5wcr__internal_navigation_column'
25
  );
26

27
  const isFirstUserCol = userCols[0]?.id === column.id || userCols[0]?.accessor === column.accessor;
950,938✔
28
  updatedCellProps['data-is-first-column'] = isFirstUserCol;
950,938✔
29

30
  if ((isFirstUserCol && rowIsExpandable) || (row.isGrouped && row.canExpand)) {
950,938✔
31
    updatedCellProps.onKeyDown = row.getToggleRowExpandedProps?.()?.onKeyDown;
34,267✔
32
    let ariaLabel = '';
34,267✔
33
    if (row.isGrouped) {
34,267✔
34
      ariaLabel += translatableTexts.groupedA11yText + ',';
16,013✔
35
    }
36
    if (row.isExpanded) {
34,267✔
37
      updatedCellProps['aria-expanded'] = 'true';
10,232✔
38
      ariaLabel += ` ${translatableTexts.collapseA11yText}`;
10,232✔
39
    } else {
40
      updatedCellProps['aria-expanded'] = 'false';
24,035✔
41
      ariaLabel += ` ${translatableTexts.expandA11yText}`;
24,035✔
42
    }
43
    updatedCellProps['aria-label'] = ariaLabel;
34,267✔
44
  } else if (
916,671✔
45
    (selectionMode !== AnalyticalTableSelectionMode.None &&
2,042,568✔
46
      selectionBehavior !== AnalyticalTableSelectionBehavior.RowSelector &&
47
      !row.isGrouped) ||
48
    column.id === '__ui5wcr__internal_selection_column'
49
  ) {
50
    if (row.isSelected) {
209,226✔
51
      updatedCellProps['aria-selected'] = 'true';
57,461✔
52
      updatedCellProps['aria-label'] = `${value ?? ''} ${translatableTexts.unselectA11yText}`;
57,461✔
53
    } else {
54
      updatedCellProps['aria-selected'] = 'false';
151,765✔
55
      updatedCellProps['aria-label'] = `${value ?? ''} ${translatableTexts.selectA11yText}`;
151,765✔
56
    }
57
  }
58

59
  return [cellProps, updatedCellProps];
950,938✔
60
};
61

62
const setHeaderProps = (headerProps, { column, instance }) => {
369✔
63
  const { translatableTexts } = instance.webComponentsReactProperties;
52,143✔
64

65
  if (!column) {
52,143!
NEW
66
    return headerProps;
×
67
  }
68
  const isFiltered = column?.filterValue && column?.filterValue.length > 0;
52,143✔
69

70
  const updatedProps = {};
52,143✔
71
  if (column.isSorted) {
52,143✔
72
    updatedProps['aria-sort'] = column.isSortedDesc ? 'descending' : 'ascending';
109✔
73
  }
74
  if (isFiltered) {
52,143✔
75
    updatedProps['aria-label'] = translatableTexts.filteredA11yText;
725✔
76
  }
77
  if (column.isGrouped) {
52,143✔
78
    if (updatedProps['aria-label']) {
792✔
79
      updatedProps['aria-label'] += ` ${translatableTexts.groupedA11yText}`;
9✔
80
    } else {
81
      updatedProps['aria-label'] = translatableTexts.groupedA11yText;
783✔
82
    }
83
  }
84

85
  return [headerProps, { isFiltered, ...updatedProps }];
52,143✔
86
};
87

88
export const useA11y = (hooks) => {
369✔
89
  hooks.getCellProps.push(setCellProps);
21,353✔
90
  hooks.getHeaderProps.push(setHeaderProps);
21,353✔
91
};
92
useA11y.pluginName = 'useA11y';
369✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc