diff --git a/packages/design-system-docs/src/pages/components/Table/_Table.docs.scss b/packages/design-system-docs/src/pages/components/Table/_Table.docs.scss index cec7622871..a0c065075d 100644 --- a/packages/design-system-docs/src/pages/components/Table/_Table.docs.scss +++ b/packages/design-system-docs/src/pages/components/Table/_Table.docs.scss @@ -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 `` tag inside of the `` 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/) diff --git a/packages/design-system-docs/src/pages/components/Table/table-complex.example.html b/packages/design-system-docs/src/pages/components/Table/table-complex.example.html index a5856b4a3a..61017c442d 100644 --- a/packages/design-system-docs/src/pages/components/Table/table-complex.example.html +++ b/packages/design-system-docs/src/pages/components/Table/table-complex.example.html @@ -8,9 +8,11 @@ - - + diff --git a/packages/design-system/src/components/Table/Table.test.jsx b/packages/design-system/src/components/Table/Table.test.jsx index e42a2cf275..e7770690a9 100644 --- a/packages/design-system/src/components/Table/Table.test.jsx +++ b/packages/design-system/src/components/Table/Table.test.jsx @@ -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 = {defaultCaptionChildren}; -function render(customProps = {}, children) { +function render(customProps = {}, children = tableCaption, deep = false) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultCaptionChildren}; - } + const component =
Address - Employment + + Address + + Employment
{children}
; return { props: props, - wrapper: shallow({children}
), + 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(); + }); + }); }); diff --git a/packages/design-system/src/components/Table/TableBody.test.jsx b/packages/design-system/src/components/Table/TableBody.test.jsx index 571bda818c..3b9f50aefe 100644 --- a/packages/design-system/src/components/Table/TableBody.test.jsx +++ b/packages/design-system/src/components/Table/TableBody.test.jsx @@ -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 = ( - - Cell a - Cell a - + + Cell a + Cell a + ); -const defaultTableBodyProps = { - className: 'foo-body', -}; -function render(customProps = {}, children) { +function render(customProps = {}) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultTableBodyChildren}; - } + const children = {defaultTableBodyChildren}; return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -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(); diff --git a/packages/design-system/src/components/Table/TableCaption.test.jsx b/packages/design-system/src/components/Table/TableCaption.test.jsx index 84c60b7971..17bd9cc927 100644 --- a/packages/design-system/src/components/Table/TableCaption.test.jsx +++ b/packages/design-system/src/components/Table/TableCaption.test.jsx @@ -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 = {defaultCaptionChildren}; - } + const children = {defaultCaptionChildren}; return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -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(); }); diff --git a/packages/design-system/src/components/Table/TableCell.test.jsx b/packages/design-system/src/components/Table/TableCell.test.jsx index dd672439ab..2d441c648d 100644 --- a/packages/design-system/src/components/Table/TableCell.test.jsx +++ b/packages/design-system/src/components/Table/TableCell.test.jsx @@ -1,147 +1,126 @@ import React from 'react'; -import Table from './Table'; import TableBody from './TableBody'; import TableCell from './TableCell'; import TableHead from './TableHead'; import TableRow from './TableRow'; import { mount } from 'enzyme'; -const defaultTableHeadChildren = ( - - Column a - Column b - -); -const defaultTableHeadProps = { - className: 'foo-head', -}; - -const defaultTableBodyChildren = ( - - Cell a - Cell b - -); -const defaultTableBodyProps = { - className: 'foo-body', -}; - -function renderHead(customProps = {}, children) { +function renderHead(customProps = {}) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultTableHeadChildren}; - } + const children = ( + + + Column a + Column b + + + ); return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -function renderBody(customProps = {}, children) { +function renderBody(customProps = {}) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultTableBodyChildren}; - } + const children = ( + + + Cell a + Cell b + + + ); return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -describe('Table', function () { - it('renders a table thead element', () => { - const data = renderHead(undefined, undefined); - const wrapper = data.wrapper; +describe('TableCell', function () { + describe('TableHead wrap: header cell - default props', () => { + it('renders a table element', () => { + const { wrapper } = renderHead(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table).toHaveLength(2); + expect(table).toHaveLength(2); - expect(wrapper).toMatchSnapshot(); - }); + expect(wrapper).toMatchSnapshot(); + }); - it('sets thead align="left"', () => { - const data = renderHead(undefined, undefined); - const wrapper = data.wrapper; + it('sets align="left"', () => { + const { wrapper } = renderHead(); + const table = wrapper.find('TableCell'); - const table = wrapper.find('TableCell'); - expect(table.first().prop('align')).toBe('left'); - }); + expect(table.first().prop('align')).toBe('left'); + }); - it('sets thead role="columnheader"', () => { - const data = renderHead(undefined, undefined); - const wrapper = data.wrapper; + it('sets role="columnheader"', () => { + const { wrapper } = renderHead(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table.first().prop('role')).toBe('columnheader'); - }); + expect(table.first().prop('role')).toBe('columnheader'); + }); - it('sets thead scope="col"', () => { - const data = renderHead(undefined, undefined); - const wrapper = data.wrapper; + it('sets scope="col"', () => { + const { wrapper } = renderHead(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table.first().prop('scope')).toBe('col'); + expect(table.first().prop('scope')).toBe('col'); + }); }); - it('renders a table tbody row element', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; - - const table = wrapper.find('TableCell'); - expect(table).toHaveLength(2); + describe('TableBody wrap: data cell - default props', () => { + it('renders TableCell component', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('TableCell'); - expect(wrapper).toMatchSnapshot(); - }); + expect(table).toHaveLength(2); + expect(wrapper).toMatchSnapshot(); + }); - it('renders a table tbody row header element which overwrites default header row component to ', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('renders a table row header element which overwrites default header row component to ', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table).toHaveLength(1); - }); + expect(table).toHaveLength(1); + }); - it('sets a table tbody role="rowheader" which overwrites default role value "cell"', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('sets a table role="rowheader" which overwrites default role value "cell"', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table.prop('role')).toBe('rowheader'); - }); + expect(table.prop('role')).toBe('rowheader'); + }); - it('sets a table tbody scope="row"', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('sets a table scope="row"', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('th'); - const table = wrapper.find('th'); - expect(table.prop('scope')).toBe('row'); - }); + expect(table.prop('scope')).toBe('row'); + }); - it('renders a table tbody row data element', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('renders a table row data element', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('td'); - const table = wrapper.find('td'); - expect(table).toHaveLength(1); - }); + expect(table).toHaveLength(1); + }); - it('sets a table tbody role="cell"', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('sets a table role="cell"', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('td'); - const table = wrapper.find('td'); - expect(table.prop('role')).toBe('cell'); - }); + expect(table.prop('role')).toBe('cell'); + }); - it('sets a table tbody scope="row"', () => { - const data = renderBody(undefined, undefined); - const wrapper = data.wrapper; + it('sets a table scope="row"', () => { + const { wrapper } = renderBody(); + const table = wrapper.find('td'); - const table = wrapper.find('td'); - expect(table.prop('scope')).toBe('row'); + expect(table.prop('scope')).toBe('row'); + }); }); }); diff --git a/packages/design-system/src/components/Table/TableHead.test.jsx b/packages/design-system/src/components/Table/TableHead.test.jsx index 62068892b9..0b205c3480 100644 --- a/packages/design-system/src/components/Table/TableHead.test.jsx +++ b/packages/design-system/src/components/Table/TableHead.test.jsx @@ -1,40 +1,38 @@ import React from 'react'; -import Table from './Table'; import TableCell from './TableCell'; import TableHead from './TableHead'; import TableRow from './TableRow'; import { mount } from 'enzyme'; const defaultTableHeadChildren = ( - + Column a Column b ); -const defaultTableHeadProps = { - className: 'foo-head', -}; -function render(customProps = {}, children) { +function render(customProps = {}) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultTableHeadChildren}; - } + const children = {defaultTableHeadChildren}; return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -describe('Table', function () { +describe('TableHead', function () { it('renders a table head', () => { - const data = render(undefined, undefined); - const wrapper = data.wrapper; - + const { wrapper } = render(); const tableHead = wrapper.find('thead'); + expect(tableHead).toHaveLength(1); + }); + + it('renders additional attributes', () => { + const { wrapper } = render({ className: 'foo-head' }); + const tableHead = wrapper.find('thead'); + expect(tableHead.hasClass('foo-head')).toBe(true); expect(wrapper).toMatchSnapshot(); diff --git a/packages/design-system/src/components/Table/TableRow.test.jsx b/packages/design-system/src/components/Table/TableRow.test.jsx index d82fa5ff59..ecfcb78fb2 100644 --- a/packages/design-system/src/components/Table/TableRow.test.jsx +++ b/packages/design-system/src/components/Table/TableRow.test.jsx @@ -1,51 +1,45 @@ import React from 'react'; -import Table from './Table'; -import TableCell from './TableCell'; -import TableHead from './TableHead'; import TableRow from './TableRow'; import { mount } from 'enzyme'; -const defaultTableHeadChildren = ( - - Column a - Column b - -); -const defaultTableHeadProps = { - className: 'foo-head', -}; - -function render(customProps = {}, children) { +function render(customProps = {}) { const props = Object.assign({}, customProps); - - if (!children) { - children = {defaultTableHeadChildren}; - } + const children = ( + + + Column a + Column b + + + ); return { props: props, - wrapper: mount({children}
), + wrapper: mount({children}
), }; } -describe('Table', function () { +describe('TableRow', function () { it('renders a table row', () => { - const data = render(undefined, undefined); - const wrapper = data.wrapper; - + const { wrapper } = render(); const tableRow = wrapper.find('tr'); - expect(tableRow).toHaveLength(1); - expect(tableRow.hasClass('foo-row')).toBe(true); - expect(wrapper).toMatchSnapshot(); + expect(tableRow).toHaveLength(1); }); it('sets role="row"', () => { - const data = render(undefined, undefined); - const wrapper = data.wrapper; - + const { wrapper } = render(); const tableRow = wrapper.find('tr'); - expect(tableRow).toHaveLength(1); + expect(tableRow.prop('role')).toBe('row'); }); + + it('renders additional attributes', () => { + const { wrapper } = render({ className: 'foo-row' }); + const tableRow = wrapper.find('tr'); + + expect(tableRow.hasClass('foo-row')).toBe(true); + + expect(wrapper).toMatchSnapshot(); + }); }); diff --git a/packages/design-system/src/components/Table/__snapshots__/Table.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/Table.test.jsx.snap index 18f038d0d8..c985663bc0 100644 --- a/packages/design-system/src/components/Table/__snapshots__/Table.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/Table.test.jsx.snap @@ -1,13 +1,42 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table supports responsive table 1`] = ` +exports[`Table applies additional classNames to root table 1`] = ` +
+ + + Foo + +
+
+`; + +exports[`Table applies borderless classes 1`] = ` +
+ + + Foo + +
+
+`; + +exports[`Table applies responsive table 1`] = `
Foo @@ -16,9 +45,9 @@ exports[`Table supports responsive table 1`] = ` `; -exports[`Table supports scroll table 1`] = ` +exports[`Table applies scroll table 1`] = `
} - className="foo-caption" key=".0" > Foo @@ -54,14 +82,13 @@ exports[`Table supports scroll table 1`] = `
`; -exports[`Table supports zebra stripe 1`] = ` +exports[`Table applies zebra stripe classes 1`] = `
Foo @@ -69,3 +96,115 @@ exports[`Table supports zebra stripe 1`] = `
`; + +exports[`Table renders additional attributes 1`] = ` +
+ + + Foo + +
+
+`; + +exports[`Table table caption scrollable true applies scroll table wrapper and classes 1`] = ` + +

+ Scroll using arrow keys to see more +

+ + } + stackableBreakpoint="sm" +> +
+
+ +

+ Scroll using arrow keys to see more +

+ + } + key=".0" + > +
+ +
+ Foo +
+ + +`; + +exports[`Table table caption scrollable true applies scrollableNotice 1`] = ` + +
+
+ + + +
+ Foo +
+ + +`; diff --git a/packages/design-system/src/components/Table/__snapshots__/TableBody.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/TableBody.test.jsx.snap index 550e5c0303..fd18544448 100644 --- a/packages/design-system/src/components/Table/__snapshots__/TableBody.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/TableBody.test.jsx.snap @@ -1,67 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table renders a table body 1`] = ` - + + -

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
-
- - - - - - - - - - - - - - -
- Cell a - - Cell a -
- - + + + Cell a + + + Cell a + + + + + `; diff --git a/packages/design-system/src/components/Table/__snapshots__/TableCaption.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/TableCaption.test.jsx.snap index 32089b664f..0950e3b40d 100644 --- a/packages/design-system/src/components/Table/__snapshots__/TableCaption.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/TableCaption.test.jsx.snap @@ -1,38 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table renders a table caption 1`] = ` - + +
-

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
- - - - -
- Foo -
-
-
+ Foo + + + `; diff --git a/packages/design-system/src/components/Table/__snapshots__/TableCell.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/TableCell.test.jsx.snap index 4564f05b0d..7fd0e89b55 100644 --- a/packages/design-system/src/components/Table/__snapshots__/TableCell.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/TableCell.test.jsx.snap @@ -1,139 +1,83 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table renders a table tbody row element 1`] = ` - -

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
-
- - data cell - default props renders TableCell component 1`] = ` +
+ + + + - + + + - - - - - - - - - - - -
+ Cell a +
- Cell a - - Cell b -
- - + Cell b + + + +
+ + + `; -exports[`Table renders a table thead element 1`] = ` - -

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
-
- header cell - default props renders a table
element 1`] = ` + + + + - - + + + - - - - - - - - - - - -
+ Column a +
- Column a - - Column b -
- -
+ Column b + + + + + + + `; diff --git a/packages/design-system/src/components/Table/__snapshots__/TableHead.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/TableHead.test.jsx.snap index e4b81c05ce..1edf4edfbd 100644 --- a/packages/design-system/src/components/Table/__snapshots__/TableHead.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/TableHead.test.jsx.snap @@ -1,72 +1,49 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table renders a table head 1`] = ` - + + -

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
-
- - - + + + - - - - - - - - - - - -
+ Column a +
- Column a - - Column b -
- - + Column b + + + + + + + `; diff --git a/packages/design-system/src/components/Table/__snapshots__/TableRow.test.jsx.snap b/packages/design-system/src/components/Table/__snapshots__/TableRow.test.jsx.snap index 17d302cf5f..541eea54b1 100644 --- a/packages/design-system/src/components/Table/__snapshots__/TableRow.test.jsx.snap +++ b/packages/design-system/src/components/Table/__snapshots__/TableRow.test.jsx.snap @@ -1,74 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table renders a table row 1`] = ` - + + -

- Scroll using arrow keys to see more -

- - } - stackableBreakpoint="sm" -> -
-
- - - - - - - - - - - - - - -
- Column a - - Column b -
- - + + Column a + + + Column b + + + + + `; diff --git a/packages/design-system/src/styles/components/_Table.scss b/packages/design-system/src/styles/components/_Table.scss index dc6cfff609..b05f21496d 100644 --- a/packages/design-system/src/styles/components/_Table.scss +++ b/packages/design-system/src/styles/components/_Table.scss @@ -1,52 +1,12 @@ @import '../settings/index.scss'; -.ds-c-table { - border-collapse: collapse; - border-spacing: 0; - margin: 0; - - th, - thead td { - background-color: $color-gray-lightest; - text-align: left; - } - - tbody th { - font-weight: $font-normal; - } - - th, - td { - border: 1px solid $color-gray; - padding: $spacer-2; - } -} - -.ds-c-table--borderless { - thead { - tr { - background-color: transparent; - } - - th { - border-top: 0; - } - } - - th, - td { - border-left: 0; - border-right: 0; - } -} - -.ds-c-table__header--label span { - display: block; - text-align: center; - text-transform: uppercase; -} +$table-header-background-color: $color-gray-lightest !default; +$table-striped-background-color: $color-gray-lightest !default; +$table-striped-header-background-color: $color-gray-lightest !default; +// Max-width of the header column for a stacked table +$table-stacked-header-max-width: 160px !default; -@mixin ds-c-table--stacked { +@mixin table-stacked { thead tr { /* Hide column headings when responsive table stacked vertically on smaller viewports */ // ds-u-visibility--screen-reader @@ -71,7 +31,9 @@ border: 0; border-top: 1px solid; display: grid; - grid-template-columns: 120px 1fr; + // CSS grid doesn't support word-wrap. Use minmax as a workaround + // https://css-tricks.com/css-grid-in-ie-debunking-common-ie-grid-misconceptions/#fit-content-is-not-ie-friendly-but + grid-template-columns: minmax(0, $table-stacked-header-max-width) 1fr; position: relative; // stylelint-disable selector-no-qualifying-type @@ -80,8 +42,10 @@ // stylelint-enable selector-no-qualifying-type flex: none; font-weight: bold; - max-width: 120px; - width: 50%; + max-width: $table-stacked-header-max-width; + // allow for spacing on right side of data-title column + width: calc(100% - #{$spacer-2}); + word-wrap: break-word; } > * { @@ -96,18 +60,17 @@ padding-bottom: 2px; position: relative; - &::after { + &::before { background-color: $color-gray-lightest; border-right: 1px solid; bottom: 0; content: ''; display: block; left: 0; - max-width: 120px; + max-width: $table-stacked-header-max-width; position: absolute; top: 0; - width: 50%; - z-index: -9999; + width: 100%; } } @@ -116,17 +79,11 @@ border-top: 0; } - &.ds-c-table--striped tbody { - tr:nth-child(even) { - background-color: $color-gray-lightest; - } - } - &.ds-c-table--borderless { tr { border: 0; - &::after { + &::before { background-color: transparent; border-right: 0; } @@ -139,27 +96,85 @@ } } +.ds-c-table { + border-collapse: collapse; + border-spacing: 0; + margin: 0; + + th, + thead td { + background-color: $table-header-background-color; + text-align: left; + } + + tbody th { + font-weight: $font-normal; + } + + th, + td { + border: 1px solid $color-gray; + padding: $spacer-2; + } +} + +.ds-c-table--borderless { + thead { + th, + tr { + background-color: transparent; + } + + th { + border-top: 0; + } + } + + th, + td { + border-left: 0; + border-right: 0; + } +} + +.ds-c-table--stacked { + @include table-stacked; +} + .ds-c-sm-table--stacked { @media only screen and (max-width: $width-sm) { - @include ds-c-table--stacked; + @include table-stacked; } } .ds-c-md-table--stacked { @media only screen and (max-width: $width-md) { - @include ds-c-table--stacked; + @include table-stacked; } } .ds-c-lg-table--stacked { @media only screen and (max-width: $width-lg) { - @include ds-c-table--stacked; + @include table-stacked; } } -.ds-c-table--striped tbody { - tr:nth-child(even) { - background-color: $color-gray-lightest; +.ds-c-table--striped { + thead { + th, + tr { + background-color: $table-striped-header-background-color; + } + } + + tbody { + tr:nth-child(even) { + background-color: $table-striped-background-color; + } + + tr:nth-child(odd)::before { + background-color: transparent; + } } }