Skip to content

Commit

Permalink
[WNMGDS-613] Additional table props (#829)
Browse files Browse the repository at this point in the history
* Update borderless table to have header background color transparent

* Update complex table example

* Use variable to hold data title max-width

* Change zebra striped color

* Add word-wrap for data title

* Update test

* Update stacked title word wrap and remove test data

* Update tableCaption test

* Add variables for table background/stripe color

* Update scss per review feedback

* Use calc to leave space padding on right side of data-title column

* Update to use ::before pseudo element for tr instead

* Update unit test

* Update packages/design-system/src/styles/components/_Table.scss

Co-authored-by: Bernard <[email protected]>

* Fix striped stacked style

Co-authored-by: Scott Weber <[email protected]>
Co-authored-by: Bernard <[email protected]>
Co-authored-by: bernardwang <[email protected]>
  • Loading branch information
4 people authored Oct 1, 2020
1 parent 592e14d commit dcff1a3
Show file tree
Hide file tree
Showing 15 changed files with 635 additions and 644 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ Style guide: components.table.react-tablecell
- Complex tables are tables with more than two levels of headers. Each header should be given a unique `id` and each data cell should have a `headers` attribute with each related header cell’s `id` listed.
- When adding a title to a table, include it in a `<caption>` tag inside of the `<table>` element.
### Customization
The following Sass variables can be overridden to theme table fields:
- `$table-header-background-color`
- `$table-striped-background-color`
- `$table-striped-header-background-color`
- `$table-stacked-header-max-width`
### Learn more
- [W3C Web Accessibility Tutorial \- Table Concepts](https://www.w3.org/WAI/tutorials/tables/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
<thead>
<tr>
<td rowspan="1"></td>
<th colspan="2" class="ds-c-table__header--label" scope="colgroup"><span>Address</span></th>
<th colspan="2" class="ds-c-table__header--label" scope="colgroup">
<span>Employment</span>
<th colspan="2" class="ds-u-text-align--center" scope="colgroup">
Address
</th>
<th colspan="2" class="ds-u-text-align--center" scope="colgroup">
Employment
</th>
</tr>
<tr>
Expand Down
120 changes: 88 additions & 32 deletions packages/design-system/src/components/Table/Table.test.jsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,134 @@
import { mount, shallow } from 'enzyme';
import React from 'react';
import Table from './Table';
import TableCaption from './TableCaption';
import { shallow } from 'enzyme';

const defaultCaptionChildren = 'Foo';
const defaultCaptionProps = {
className: 'foo-caption',
};
const tableCaption = <TableCaption>{defaultCaptionChildren}</TableCaption>;

function render(customProps = {}, children) {
function render(customProps = {}, children = tableCaption, deep = false) {
const props = Object.assign({}, customProps);

if (!children) {
children = <TableCaption {...defaultCaptionProps}>{defaultCaptionChildren}</TableCaption>;
}
const component = <Table {...props}>{children}</Table>;

return {
props: props,
wrapper: shallow(<Table {...props}>{children}</Table>),
wrapper: deep ? mount(component) : shallow(component),
};
}

describe('Table', function () {
it('renders a table', () => {
const data = render(undefined, undefined);
const wrapper = data.wrapper;

const { wrapper } = render();
const table = wrapper.find('table');

expect(table).toHaveLength(1);

expect(table.hasClass('ds-c-table')).toBe(true);
});

it('sets role="table"', () => {
const data = render(undefined, undefined);
const wrapper = data.wrapper;

const { wrapper } = render();
const table = wrapper.find('table');
expect(table).toHaveLength(1);

expect(table.prop('role')).toBe('table');
});

it('supports zebra stripe', () => {
const data = render({ striped: true }, undefined);
const wrapper = data.wrapper;
it('applies additional classNames to root table', () => {
const { wrapper } = render({ className: 'foo-table' });
const table = wrapper.find('table');

expect(table.hasClass('foo-table')).toBe(true);

expect(wrapper).toMatchSnapshot();
});

it('applies borderless classes', () => {
const { wrapper } = render({ borderless: true });
const table = wrapper.find('table');
expect(table.hasClass('ds-c-table')).toBe(true);
expect(table.hasClass('ds-c-table--striped')).toBe(true);

expect(table.hasClass('ds-c-table--borderless')).toBe(true);

expect(wrapper).toMatchSnapshot();
});

it('supports responsive table', () => {
const data = render({ stackable: true, stackableBreakpoint: 'lg' }, undefined);
const wrapper = data.wrapper;
it('applies zebra stripe classes', () => {
const { wrapper } = render({ striped: true });
const table = wrapper.find('table');

expect(table.hasClass('ds-c-table--striped')).toBe(true);

expect(wrapper).toMatchSnapshot();
});

it('applies responsive table', () => {
const { wrapper } = render({ stackable: true, stackableBreakpoint: 'lg' });
const table = wrapper.find('table');
expect(table.hasClass('ds-c-table')).toBe(true);

expect(table.hasClass('ds-c-lg-table--stacked')).toBe(true);

expect(wrapper).toMatchSnapshot();
});

it('supports scroll table', () => {
const data = render({ scrollable: true }, undefined);
const wrapper = data.wrapper;
it('applies scroll table', () => {
const { wrapper } = render({ scrollable: true });
const divWrapper = wrapper.find('div');

const table = wrapper.find('table');
const divWrapper = data.wrapper.find('div');
expect(table.hasClass('ds-c-table')).toBe(true);
expect(divWrapper.hasClass('ds-c-table__wrapper')).toBe(true);

expect(wrapper).toMatchSnapshot();
});

it('renders additional attributes', () => {
const { wrapper } = render({ ariaLabel: 'test additional attribute' });
const table = wrapper.find('table');

expect(table.prop('ariaLabel')).toBe('test additional attribute');

expect(wrapper).toMatchSnapshot();
});

describe('table caption scrollable true', () => {
it('applies scroll table wrapper and classes', () => {
const { wrapper } = render({ scrollable: true }, undefined, true);
const divWrapper = wrapper.find('div');

expect(wrapper.prop('scrollable')).toBe(true);

expect(divWrapper.hasClass('ds-c-table__wrapper')).toBe(true);
expect(divWrapper.prop('role')).toBe('region');
expect(divWrapper.prop('aria-live')).toBe('polite');
expect(divWrapper.prop('aria-relevant')).toBe('additions');
expect(divWrapper.prop('tabindex')).toBeUndefined();

expect(wrapper).toMatchSnapshot();
});

it('scroll table aria-labelledby matches caption id', () => {
const { wrapper } = render({ scrollable: true }, undefined, true);
const divWrapper = wrapper.find('div');
const caption = wrapper.find('caption');

expect(caption.prop('id')).toBe(divWrapper.prop('aria-labelledby'));
});

it('contains scroll table notice ', () => {
const { wrapper } = render({ scrollable: true }, undefined, true);
const tableCaption = wrapper.find('TableCaption');

expect(tableCaption.prop('_scrollableNotice')).toBeDefined();
});

it('applies scrollableNotice', () => {
const { wrapper } = render(
{ scrollable: true, scrollableNotice: 'foo scrollable notice' },
undefined,
true
);
const tableCaption = wrapper.find('TableCaption');

expect(tableCaption.prop('_scrollableNotice')).toBe('foo scrollable notice');

expect(wrapper).toMatchSnapshot();
});
});
});
37 changes: 17 additions & 20 deletions packages/design-system/src/components/Table/TableBody.test.jsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
import React from 'react';
import Table from './Table';

import TableBody from './TableBody';
import TableCell from './TableCell';
import TableRow from './TableRow';
import { mount } from 'enzyme';

const defaultTableBodyChildren = (
<TableRow key="1">
<TableCell>Cell a</TableCell>
<TableCell>Cell a</TableCell>
</TableRow>
<tr>
<td>Cell a</td>
<td>Cell a</td>
</tr>
);
const defaultTableBodyProps = {
className: 'foo-body',
};

function render(customProps = {}, children) {
function render(customProps = {}) {
const props = Object.assign({}, customProps);

if (!children) {
children = <TableBody {...defaultTableBodyProps}>{defaultTableBodyChildren}</TableBody>;
}
const children = <TableBody {...props}>{defaultTableBodyChildren}</TableBody>;

return {
props: props,
wrapper: mount(<Table {...props}>{children}</Table>),
wrapper: mount(<table>{children}</table>),
};
}

describe('Table', function () {
describe('TableBody', function () {
it('renders a table body', () => {
const data = render(undefined, undefined);
const wrapper = data.wrapper;

const { wrapper } = render();
const tableBody = wrapper.find('tbody');

expect(tableBody).toHaveLength(1);
});

it('renders additional attributes', () => {
const { wrapper } = render({ className: 'foo-body' });
const tableBody = wrapper.find('tbody');

expect(tableBody.hasClass('foo-body')).toBe(true);

expect(wrapper).toMatchSnapshot();
Expand Down
32 changes: 16 additions & 16 deletions packages/design-system/src/components/Table/TableCaption.test.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import React from 'react';
import Table from './Table';
import TableCaption from './TableCaption';
import { mount } from 'enzyme';

const defaultCaptionChildren = 'Foo';
const defaultCaptionProps = {
className: 'foo-caption',
};

function render(customProps = {}, children) {
function render(customProps = {}) {
const props = Object.assign({}, customProps);

if (!children) {
children = <TableCaption {...defaultCaptionProps}>{defaultCaptionChildren}</TableCaption>;
}
const children = <TableCaption {...props}>{defaultCaptionChildren}</TableCaption>;

return {
props: props,
wrapper: mount(<Table {...props}>{children}</Table>),
wrapper: mount(<table>{children}</table>),
};
}

describe('Table', function () {
describe('TableCaption', function () {
it('renders a table caption', () => {
const data = render(undefined, undefined);
const wrapper = data.wrapper;
const { wrapper } = render();
const caption = wrapper.find('caption');

expect(caption).toHaveLength(1);
expect(caption.hasClass('ds-c-table__caption')).toBe(true);
expect(caption.text()).toBe(defaultCaptionChildren);
});

it('applies additional classNames to caption', () => {
const { wrapper } = render({ className: 'foo-caption' });
const caption = wrapper.find('caption');

const table = wrapper.find('caption');
expect(table).toHaveLength(1);
expect(table.hasClass('ds-c-table__caption')).toBe(true);
expect(caption.hasClass('foo-caption')).toBe(true);

expect(wrapper).toMatchSnapshot();
});
Expand Down
Loading

0 comments on commit dcff1a3

Please sign in to comment.