Skip to content

Commit

Permalink
Fix Table aria attributes (bvaughn#1208)
Browse files Browse the repository at this point in the history
* Fix Table accessibility

Add aria attributes, following https://www.w3.org/TR/2018/NOTE-wai-aria-practices-1.1-20180726/examples/grid/dataGrids.html#rps_label

* Fixes after review
  • Loading branch information
jsomsanith-tlnd authored and wuweiweiwu committed Oct 2, 2018
1 parent 3a1662f commit 15e0791
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules
npm-debug.log
styles.css
.vscode
.idea
48 changes: 48 additions & 0 deletions source/Table/Table.jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,25 @@ describe('Table', () => {
expect(node.getAttribute('role')).toEqual('grid');
});

it('should set aria col/row count on the table', () => {
const node = findDOMNode(render(getMarkup()));
expect(node.getAttribute('aria-colcount')).toEqual('2');
expect(node.getAttribute('aria-rowcount')).toEqual(`${list.size}`);
});

it('should pass down aria labels on the table', () => {
const node = findDOMNode(
render(
getMarkup({
'aria-label': 'my-table-label',
'aria-labelledby': 'my-table-label-id',
}),
),
);
expect(node.getAttribute('aria-label')).toEqual('my-table-label');
expect(node.getAttribute('aria-labelledby')).toEqual('my-table-label-id');
});

it('should set aria role on the header row', () => {
const rendered = findDOMNode(render(getMarkup()));
const row = rendered.querySelector('.ReactVirtualized__Table__headerRow');
Expand All @@ -1209,6 +1228,13 @@ describe('Table', () => {
expect(row.getAttribute('role')).toEqual('row');
});

it('should set aria rowindex on a row', () => {
const rendered = findDOMNode(render(getMarkup()));
const rows = rendered.querySelectorAll('.ReactVirtualized__Table__row');
expect(rows[0].getAttribute('aria-rowindex')).toEqual('1');
expect(rows[1].getAttribute('aria-rowindex')).toEqual('2');
});

it('should set aria role on a cell', () => {
const rendered = findDOMNode(render(getMarkup()));
const cell = rendered.querySelector(
Expand All @@ -1217,6 +1243,15 @@ describe('Table', () => {
expect(cell.getAttribute('role')).toEqual('gridcell');
});

it('should set aria colindex on a cell', () => {
const rendered = findDOMNode(render(getMarkup()));
const cells = rendered.querySelectorAll(
'.ReactVirtualized__Table__rowColumn',
);
expect(cells[0].getAttribute('aria-colindex')).toEqual('1');
expect(cells[1].getAttribute('aria-colindex')).toEqual('2');
});

it('should set aria-describedby on a cell when the column has an id', () => {
const columnID = 'column-header-test';
const rendered = findDOMNode(
Expand Down Expand Up @@ -1296,6 +1331,19 @@ describe('Table', () => {
expect(header.getAttribute('aria-sort')).toEqual('descending');
});

it('should set aria-sort to "none" if the column is sortable but not the current sort', () => {
const rendered = findDOMNode(
render(getMarkup({disableSort: true, sort: jest.fn()})),
);
const headers = rendered.querySelectorAll(
'.ReactVirtualized__Table__headerColumn',
);
// the first column is not sortable
expect(headers[0].getAttribute('aria-sort')).toBe(null);
// the second column is sortable
expect(headers[1].getAttribute('aria-sort')).toEqual('none');
});

it('should set id on a header column when the column has an id', () => {
const columnID = 'column-header-test';
const rendered = findDOMNode(
Expand Down
10 changes: 10 additions & 0 deletions source/Table/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ import SortDirection from './SortDirection';
*/
export default class Table extends React.PureComponent {
static propTypes = {
/** This is just set on the grid top element. */
'aria-label': PropTypes.string,

/** This is just set on the grid top element. */
'aria-labelledby': PropTypes.string,

/**
* Removes fixed height from the scrollingContainer so that the total height
* of rows can stretch the window. Intended for use with WindowScroller
Expand Down Expand Up @@ -383,6 +387,10 @@ export default class Table extends React.PureComponent {
// Any property that should trigger a re-render of Grid then is specified here to avoid a stale display.
return (
<div
aria-label={this.props['aria-label']}
aria-labelledby={this.props['aria-labelledby']}
aria-colcount={React.Children.toArray(children).length}
aria-rowcount={this.props.rowCount}
className={cn('ReactVirtualized__Table', className)}
id={id}
role="grid"
Expand Down Expand Up @@ -456,6 +464,7 @@ export default class Table extends React.PureComponent {
// See PR https://github.com/bvaughn/react-virtualized/pull/942
return (
<div
aria-colindex={columnIndex + 1}
aria-describedby={id}
className={cn('ReactVirtualized__Table__rowColumn', className)}
key={'Row' + rowIndex + '-' + 'Col' + columnIndex}
Expand Down Expand Up @@ -545,6 +554,7 @@ export default class Table extends React.PureComponent {
};

headerAriaLabel = column.props['aria-label'] || label || dataKey;
headerAriaSort = 'none';
headerTabIndex = 0;
headerOnClick = onClick;
headerOnKeyDown = onKeyDown;
Expand Down
2 changes: 1 addition & 1 deletion source/Table/defaultRowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function defaultRowRenderer({
rowData,
style,
}: RowRendererParams) {
const a11yProps = {};
const a11yProps = {'aria-rowindex': index + 1};

if (
onRowClick ||
Expand Down

0 comments on commit 15e0791

Please sign in to comment.