From bd8459b41450bb29088942df3d04aeffecc89d90 Mon Sep 17 00:00:00 2001 From: Tyler Hallada Date: Tue, 20 Mar 2018 11:46:33 -0400 Subject: [PATCH] feat(table): Add tableFixed option to set col widths (#179) --- .../__snapshots__/Storyshots.test.js.snap | 669 +++++++++++++++--- src/Table/README.md | 22 +- src/Table/Table.scss | 4 + src/Table/Table.stories.jsx | 18 +- src/Table/Table.test.jsx | 65 ++ src/Table/index.jsx | 21 +- 6 files changed, 684 insertions(+), 115 deletions(-) diff --git a/.storybook/__snapshots__/Storyshots.test.js.snap b/.storybook/__snapshots__/Storyshots.test.js.snap index 9602887c84..120562815d 100644 --- a/.storybook/__snapshots__/Storyshots.test.js.snap +++ b/.storybook/__snapshots__/Storyshots.test.js.snap @@ -13929,7 +13929,9 @@ exports[`Storyshots Table default heading 1`] = ` - + - - + + + Lil Bub + + + weird tongue + + + brown tabby + + + + + Grumpy Cat + + + serving moods + + + siamese + + + + + Smoothie + + + modeling + + + orange tabby + + + + + Maru + + + being a lovable oaf + + + brown tabby + + + + + Keyboard Cat + + + piano virtuoso + + + orange tabby + + + + + Long Cat + + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + + russian white + + + + +`; + +exports[`Storyshots Table fixed 1`] = ` + + + + + + + + + + + + - - - - + - - - - + - - - - + - - - - + - - + + + + +
+ Famous Internet Cats +
+ Name + + Famous For + + +
Lil Bub + weird tongue + brown tabby
+
Grumpy Cat + serving moods + siamese
+
Smoothie + modeling + orange tabby
+
Maru + being a lovable oaf + brown tabby
+
Keyboard Cat + piano virtuoso + orange tabby
+ Long Cat + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + russian white +
`; @@ -14022,7 +14237,9 @@ exports[`Storyshots Table responsive 1`] = ` - + - - + + Lil Bub - + weird tongue - + brown tabby - - + + Grumpy Cat - + serving moods - + siamese - - + + Smoothie - + modeling - + orange tabby - - + + Maru - + being a lovable oaf - + brown tabby - - + + Keyboard Cat - + piano virtuoso - + orange tabby + + + Long Cat + + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + + russian white + + `; @@ -14115,7 +14391,9 @@ exports[`Storyshots Table sortable 1`] = ` - + - - + + Smoothie - + modeling - + orange tabby - - + + Maru - + being a lovable oaf - + brown tabby - - + + + Long Cat + + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + + russian white + + + + Lil Bub - + weird tongue - + brown tabby - - + + Keyboard Cat - + piano virtuoso - + orange tabby - - + + Grumpy Cat - + serving moods - + siamese @@ -14229,7 +14566,9 @@ exports[`Storyshots Table table-striped 1`] = ` - + - - + + Lil Bub - + weird tongue - + brown tabby - - + + Grumpy Cat - + serving moods - + siamese - - + + Smoothie - + modeling - + orange tabby - - + + Maru - + being a lovable oaf - + brown tabby - - + + Keyboard Cat - + piano virtuoso - + orange tabby + + + Long Cat + + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + + russian white + + `; @@ -14322,7 +14720,9 @@ exports[`Storyshots Table unstyled 1`] = ` - + - - + + Lil Bub - + weird tongue - + brown tabby - - + + Grumpy Cat - + serving moods - + siamese - - + + Smoothie - + modeling - + orange tabby - - + + Maru - + being a lovable oaf - + brown tabby - - + + Keyboard Cat - + piano virtuoso - + orange tabby + + + Long Cat + + + being loooooooooooooooooooooooooooooooooooooooooooooooooooooong + + + russian white + + `; diff --git a/src/Table/README.md b/src/Table/README.md index b702cc58bc..5022890c10 100644 --- a/src/Table/README.md +++ b/src/Table/README.md @@ -12,6 +12,7 @@ Provides a very basic table component with col-scoped headings displayed in the 3. `columnSortable` (boolean; optional) specifies at the column-level whether the column is sortable. If `columnSortable` is `true`, a sort button will be rendered in the column table heading. It is only required if `tableSortable` is set to `true`. 4. `onSort` (function; conditionally required) specifies what function is called when a sortable column is clicked. It is only required if the column's `columnSortable` is set to `true`. 5. `hideHeader` (boolean; optional) specifies at the column-level whether the column label is visible. A column that is sortable cannot have its label be hidden. +6. `width` (string; conditionally required) only if `hasFixedColumnWidths` is set to `true`, the `` elements' `class` attributes will be set to this value. This allows restricting columns to specific widths. See [Bootstrap's grid documentation](https://getbootstrap.com/docs/4.0/layout/grid/) for `col` class names that can be used. The order of objects in `columns` specifies the order of the columns in the table. @@ -24,16 +25,16 @@ Specifies the key of the column that is sorted by default. It is only required i ### `defaultSortDirection` (string; conditionally required) Specifies the direction the `defaultSortedColumn` is sorted in by default; it will typically be either 'asc' or 'desc'. It is only required if `tableSortable` is set to `true`. -### `caption` (string or element; optional) +### `caption` (string or element; optional, default: `null`) Specifies a descriptive caption to be applied to the entire table. -### `className` (string array; optional) +### `className` (string array; optional; default: `[]`) Specifies Bootstrap class names to apply to the table. See [Bootstrap's table documentation](https://getbootstrap.com/docs/4.0/content/tables/) for a list of applicable class names. -### `headingClassName` (string array; optional) +### `headingClassName` (string array; optional; default: `[]`) Specifies Bootstrap class names to apply to the table heading. Options are detailed in [Bootstrap's docs](https://getbootstrap.com/docs/4.0/content/tables/#table-head-options). -### `tableSortable` (boolean; optional) +### `tableSortable` (boolean; optional; default: `false`) Specifies whether the table is sortable. This setting supercedes column-level sortability, so if it is `false`, no sortable components will be rendered. ### `sortButtonsScreenReaderText` (object; conditionally required) @@ -44,3 +45,16 @@ Specifies the screen reader only text that accompanies the sort buttons for sort 3. `defaultText`: (string) specifies the screen reader only text for sort buttons that are not engaged. It is only required if `tableSortable` is set to `true`. + +Default: + +```javascript +{ + asc: 'sort ascending', + desc: 'sort descending', + defaultText: 'click to sort', +} +``` + +### `hasFixedColumnWidths` (boolean; optional; default: `false`) +Specifies whether the table's columns have fixed widths. Every element in `columns` must define a `width` if this is `true`. diff --git a/src/Table/Table.scss b/src/Table/Table.scss index 3016c770f1..f3771e91cf 100644 --- a/src/Table/Table.scss +++ b/src/Table/Table.scss @@ -6,3 +6,7 @@ @extend .p-0; font-weight: $font-weight-bold; } + +.table th, .table td { + word-wrap: break-word; +} diff --git a/src/Table/Table.stories.jsx b/src/Table/Table.stories.jsx index f688411033..7bf8f7af0b 100644 --- a/src/Table/Table.stories.jsx +++ b/src/Table/Table.stories.jsx @@ -29,6 +29,11 @@ const catData = [ color: 'orange tabby', famous_for: 'piano virtuoso', }, + { + name: 'Long Cat', + color: 'russian white', + famous_for: 'being loooooooooooooooooooooooooooooooooooooooooooooooooooooong', + }, ]; const catColumns = [ @@ -37,12 +42,14 @@ const catColumns = [ key: 'name', columnSortable: true, onSort: () => {}, + width: 'col-3', }, { label: 'Famous For', key: 'famous_for', columnSortable: false, onSort: () => {}, + width: 'col-6', }, { label: 'Coat Color', @@ -50,6 +57,7 @@ const catColumns = [ columnSortable: false, hideHeader: true, onSort: () => {}, + width: 'col-3', }, ]; @@ -113,4 +121,12 @@ storiesOf('Table', module) defaultSortedColumn={catColumns[0].key} defaultSortDirection="desc" />); - }); + }) + .add('fixed', () => ( + + )); diff --git a/src/Table/Table.test.jsx b/src/Table/Table.test.jsx index dce43742b5..68383ba4f8 100644 --- a/src/Table/Table.test.jsx +++ b/src/Table/Table.test.jsx @@ -55,6 +55,29 @@ const sortableProps = { defaultSortDirection: 'desc', }; +const fixedColumnProps = { + num: { width: 'col-4' }, + x2: { width: 'col-2' }, + sq: { width: 'col-3' }, + i: { width: 'col-3' }, +}; + +const fixedColumns = props.columns.map(column => ({ + ...column, + ...fixedColumnProps[column.key], +})); + +const fixedProps = { + ...props, + columns: fixedColumns, + hasFixedColumnWidths: true, +}; + +const propsWithColWidths = { + ...props, + columns: fixedColumns, +}; + describe('
', () => { describe('renders', () => { const wrapper = shallow(
); @@ -260,4 +283,46 @@ describe('
', () => { expect(x2Spy).toBeCalledWith('desc'); }); }); + describe('that is fixed', () => { + const wrapper = shallow(
); + + it('with col width classnames on headings', () => { + const tableHeadings = wrapper.find('th'); + + expect(tableHeadings).toHaveLength(fixedProps.columns.length); + expect(tableHeadings.at(0).hasClass('col-4')).toEqual(true); + expect(tableHeadings.at(1).hasClass('col-2')).toEqual(true); + expect(tableHeadings.at(2).hasClass('col-3')).toEqual(true); + }); + + it('with col width classnames on cells', () => { + const tableCells = wrapper.find('td'); + + expect(tableCells).toHaveLength(fixedProps.columns.length * fixedProps.data.length); + expect(tableCells.at(0).hasClass('col-4')).toEqual(true); + expect(tableCells.at(1).hasClass('col-2')).toEqual(true); + expect(tableCells.at(2).hasClass('col-3')).toEqual(true); + }); + }); + describe('that is not fixed with col widths', () => { + const wrapper = shallow(
); + + it('with no col width classnames on headings', () => { + const tableHeadings = wrapper.find('th'); + + expect(tableHeadings).toHaveLength(fixedProps.columns.length); + expect(tableHeadings.at(0).hasClass('col-4')).toEqual(false); + expect(tableHeadings.at(1).hasClass('col-2')).toEqual(false); + expect(tableHeadings.at(2).hasClass('col-3')).toEqual(false); + }); + + it('with no col width classnames on cells', () => { + const tableCells = wrapper.find('td'); + + expect(tableCells).toHaveLength(fixedProps.columns.length * fixedProps.data.length); + expect(tableCells.at(0).hasClass('col-4')).toEqual(false); + expect(tableCells.at(1).hasClass('col-2')).toEqual(false); + expect(tableCells.at(2).hasClass('col-3')).toEqual(false); + }); + }); }); diff --git a/src/Table/index.jsx b/src/Table/index.jsx index c38e7e06e4..acc594b13c 100644 --- a/src/Table/index.jsx +++ b/src/Table/index.jsx @@ -93,10 +93,13 @@ class Table extends React.Component { styles[className]))} > - + {this.props.columns.map(col => ( {this.props.data.map((row, i) => ( - - {this.props.columns.map(col => ( - + + {this.props.columns.map(({ key, width }) => ( + ))} ))} @@ -153,9 +161,11 @@ Table.propTypes = { columnSortable: isRequiredIf(PropTypes.bool, props => props.tableSortable), onSort: isRequiredIf(PropTypes.func, props => props.columnSortable), hideHeader: PropTypes.bool, + width: isRequiredIf(PropTypes.string, props => props.hasFixedColumnWidths), })).isRequired, headingClassName: PropTypes.arrayOf(PropTypes.string), tableSortable: PropTypes.bool, + hasFixedColumnWidths: PropTypes.bool, /* eslint-disable react/require-default-props */ defaultSortedColumn: isRequiredIf(PropTypes.string, props => props.tableSortable), /* eslint-disable react/require-default-props */ @@ -175,6 +185,7 @@ Table.defaultProps = { className: [], headingClassName: [], tableSortable: false, + hasFixedColumnWidths: false, sortButtonsScreenReaderText: { asc: 'sort ascending', desc: 'sort descending',
@@ -112,9 +115,14 @@ class Table extends React.Component { return (
{row[col.key]}
+ {row[key]} +