Skip to content

Commit

Permalink
[Table] Add role if the default role of elements can't be used (#20475)
Browse files Browse the repository at this point in the history
  • Loading branch information
arturbien authored Apr 10, 2020
1 parent 601bbbc commit 89d7ad0
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 15 deletions.
5 changes: 4 additions & 1 deletion packages/material-ui/src/Table/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ export const styles = (theme) => ({
},
});

const defaultComponent = 'table';

const Table = React.forwardRef(function Table(props, ref) {
const {
classes,
className,
component: Component = 'table',
component: Component = defaultComponent,
padding = 'default',
size = 'medium',
stickyHeader = false,
Expand All @@ -44,6 +46,7 @@ const Table = React.forwardRef(function Table(props, ref) {
return (
<TableContext.Provider value={table}>
<Component
role={Component === defaultComponent ? null : 'table'}
ref={ref}
className={clsx(classes.root, { [classes.stickyHeader]: stickyHeader }, className)}
{...other}
Expand Down
5 changes: 5 additions & 0 deletions packages/material-ui/src/Table/Table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ describe('<Table />', () => {
const { container } = render(<Table component="div">foo</Table>);
expect(container.firstChild).to.have.property('nodeName', 'DIV');
});

it('sets role="table"', () => {
const { container } = render(<Table component="div">foo</Table>);
expect(container.firstChild).to.have.attribute('role', 'table');
});
});

it('should render children', () => {
Expand Down
11 changes: 9 additions & 2 deletions packages/material-ui/src/TableBody/TableBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ const tablelvl2 = {
variant: 'body',
};

const defaultComponent = 'tbody';

const TableBody = React.forwardRef(function TableBody(props, ref) {
const { classes, className, component: Component = 'tbody', ...other } = props;
const { classes, className, component: Component = defaultComponent, ...other } = props;

return (
<Tablelvl2Context.Provider value={tablelvl2}>
<Component className={clsx(classes.root, className)} ref={ref} {...other} />
<Component
className={clsx(classes.root, className)}
ref={ref}
role={Component === defaultComponent ? null : 'rowgroup'}
{...other}
/>
</Tablelvl2Context.Provider>
);
});
Expand Down
16 changes: 15 additions & 1 deletion packages/material-ui/src/TableBody/TableBody.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import describeConformance from '../test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import TableBody from './TableBody';
import Tablelvl2Context from '../Table/Tablelvl2Context';

describe('<TableBody />', () => {
let mount;
let classes;
const render = createClientRender();

function mountInTable(node) {
const wrapper = mount(<table>{node}</table>);
Expand Down Expand Up @@ -53,4 +55,16 @@ describe('<TableBody />', () => {
);
assert.strictEqual(context.variant, 'body');
});

describe('prop: component', () => {
it('can render a different component', () => {
const { container } = render(<TableBody component="div" />);
expect(container.firstChild).to.have.property('nodeName', 'DIV');
});

it('sets role="rowgroup"', () => {
const { container } = render(<TableBody component="div" />);
expect(container.firstChild).to.have.attribute('role', 'rowgroup');
});
});
});
8 changes: 6 additions & 2 deletions packages/material-ui/src/TableCell/TableCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,18 @@ const TableCell = React.forwardRef(function TableCell(props, ref) {
const table = React.useContext(TableContext);
const tablelvl2 = React.useContext(Tablelvl2Context);

const isHeadCell = tablelvl2 && tablelvl2.variant === 'head';
let role;
let Component;
if (component) {
Component = component;
role = isHeadCell ? 'columnheader' : 'cell';
} else {
Component = tablelvl2 && tablelvl2.variant === 'head' ? 'th' : 'td';
Component = isHeadCell ? 'th' : 'td';
}

let scope = scopeProp;
if (!scope && tablelvl2 && tablelvl2.variant === 'head') {
if (!scope && isHeadCell) {
scope = 'col';
}
const padding = paddingProp || (table && table.padding ? table.padding : 'default');
Expand All @@ -157,6 +160,7 @@ const TableCell = React.forwardRef(function TableCell(props, ref) {
className,
)}
aria-sort={ariaSort}
role={role}
scope={scope}
{...other}
/>
Expand Down
11 changes: 9 additions & 2 deletions packages/material-ui/src/TableFooter/TableFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ const tablelvl2 = {
variant: 'footer',
};

const defaultComponent = 'tfoot';

const TableFooter = React.forwardRef(function TableFooter(props, ref) {
const { classes, className, component: Component = 'tfoot', ...other } = props;
const { classes, className, component: Component = defaultComponent, ...other } = props;

return (
<Tablelvl2Context.Provider value={tablelvl2}>
<Component className={clsx(classes.root, className)} ref={ref} {...other} />
<Component
className={clsx(classes.root, className)}
ref={ref}
role={Component === defaultComponent ? null : 'rowgroup'}
{...other}
/>
</Tablelvl2Context.Provider>
);
});
Expand Down
16 changes: 15 additions & 1 deletion packages/material-ui/src/TableFooter/TableFooter.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import describeConformance from '../test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import TableFooter from './TableFooter';
import Tablelvl2Context from '../Table/Tablelvl2Context';

describe('<TableFooter />', () => {
let mount;
let classes;
const render = createClientRender();

function mountInTable(node) {
const wrapper = mount(<table>{node}</table>);
Expand Down Expand Up @@ -51,4 +53,16 @@ describe('<TableFooter />', () => {
);
assert.strictEqual(context.variant, 'footer');
});

describe('prop: component', () => {
it('can render a different component', () => {
const { container } = render(<TableFooter component="div" />);
expect(container.firstChild).to.have.property('nodeName', 'DIV');
});

it('sets role="rowgroup"', () => {
const { container } = render(<TableFooter component="div" />);
expect(container.firstChild).to.have.attribute('role', 'rowgroup');
});
});
});
11 changes: 9 additions & 2 deletions packages/material-ui/src/TableHead/TableHead.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ const tablelvl2 = {
variant: 'head',
};

const defaultComponent = 'thead';

const TableHead = React.forwardRef(function TableHead(props, ref) {
const { classes, className, component: Component = 'thead', ...other } = props;
const { classes, className, component: Component = defaultComponent, ...other } = props;

return (
<Tablelvl2Context.Provider value={tablelvl2}>
<Component className={clsx(classes.root, className)} ref={ref} {...other} />
<Component
className={clsx(classes.root, className)}
ref={ref}
role={Component === defaultComponent ? null : 'rowgroup'}
{...other}
/>
</Tablelvl2Context.Provider>
);
});
Expand Down
16 changes: 15 additions & 1 deletion packages/material-ui/src/TableHead/TableHead.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import describeConformance from '../test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import TableHead from './TableHead';
import Tablelvl2Context from '../Table/Tablelvl2Context';

describe('<TableHead />', () => {
let mount;
let classes;
const render = createClientRender();
function mountInTable(node) {
const wrapper = mount(<table>{node}</table>);
return wrapper.find('table').childAt(0);
Expand Down Expand Up @@ -50,4 +52,16 @@ describe('<TableHead />', () => {
);
assert.strictEqual(context.variant, 'head');
});

describe('prop: component', () => {
it('can render a different component', () => {
const { container } = render(<TableHead component="div" />);
expect(container.firstChild).to.have.property('nodeName', 'DIV');
});

it('sets role="rowgroup"', () => {
const { container } = render(<TableHead component="div" />);
expect(container.firstChild).to.have.attribute('role', 'rowgroup');
});
});
});
4 changes: 3 additions & 1 deletion packages/material-ui/src/TableRow/TableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const styles = (theme) => ({
footer: {},
});

const defaultComponent = 'tr';
/**
* Will automatically set dynamic row height
* based on the material table element parent (head, body, etc).
Expand All @@ -38,7 +39,7 @@ const TableRow = React.forwardRef(function TableRow(props, ref) {
const {
classes,
className,
component: Component = 'tr',
component: Component = defaultComponent,
hover = false,
selected = false,
...other
Expand All @@ -58,6 +59,7 @@ const TableRow = React.forwardRef(function TableRow(props, ref) {
},
className,
)}
role={Component === defaultComponent ? null : 'row'}
{...other}
/>
);
Expand Down
16 changes: 15 additions & 1 deletion packages/material-ui/src/TableRow/TableRow.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import * as React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import describeConformance from '../test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import TableRow from './TableRow';

describe('<TableRow />', () => {
let mount;
let classes;
const render = createClientRender();
function mountInTable(node) {
const wrapper = mount(
<table>
Expand Down Expand Up @@ -38,4 +40,16 @@ describe('<TableRow />', () => {
const wrapper = mountInTable(<TableRow>{children}</TableRow>);
assert.strictEqual(wrapper.contains(children), true);
});

describe('prop: component', () => {
it('can render a different component', () => {
const { container } = render(<TableRow component="div" />);
expect(container.firstChild).to.have.property('nodeName', 'DIV');
});

it('sets role="rowgroup"', () => {
const { container } = render(<TableRow component="div" />);
expect(container.firstChild).to.have.attribute('role', 'row');
});
});
});
32 changes: 31 additions & 1 deletion packages/material-ui/test/integration/TableCell.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import * as React from 'react';
import { assert } from 'chai';
import { assert, expect } from 'chai';
import { createMount, findOutermostIntrinsic, getClasses } from '@material-ui/core/test-utils';
import { createClientRender } from 'test/utils/createClientRender';
import TableCell from '@material-ui/core/TableCell';
import TableFooter from '@material-ui/core/TableFooter';
import TableHead from '@material-ui/core/TableHead';
import TableBody from '@material-ui/core/TableBody';

describe('<TableRow> integration', () => {
let classes;
let mount;
const render = createClientRender();
function mountInTable(node, Variant) {
const wrapper = mount(
<table>
Expand Down Expand Up @@ -76,4 +79,31 @@ describe('<TableRow> integration', () => {
const wrapper = mountInTable(<TableCell variant="footer" />, TableHead);
assert.strictEqual(wrapper.find('th').hasClass(classes.footer), true);
});

it('sets role="columnheader" when "component" prop is set and used in the context of table head', () => {
const { getByTestId } = render(
<TableHead component="div">
<TableCell component="div" data-testid="cell" />,
</TableHead>,
);
expect(getByTestId('cell')).to.have.attribute('role', 'columnheader');
});

it('sets role="cell" when "component" prop is set and used in the context of table body ', () => {
const { getByTestId } = render(
<TableBody component="div">
<TableCell component="div" data-testid="cell" />,
</TableBody>,
);
expect(getByTestId('cell')).to.have.attribute('role', 'cell');
});

it('sets role="cell" when "component" prop is set and used in the context of table footer ', () => {
const { getByTestId } = render(
<TableFooter component="div">
<TableCell component="div" data-testid="cell" />,
</TableFooter>,
);
expect(getByTestId('cell')).to.have.attribute('role', 'cell');
});
});

0 comments on commit 89d7ad0

Please sign in to comment.