Skip to content

Commit

Permalink
feat(table-grid): add Table Grid component
Browse files Browse the repository at this point in the history
affects: patternfly-react-extensions

The table grid component is used to create a bootstrap grid based table with headers that are able to
be used for sort selection.
  • Loading branch information
jeff-phillips-18 committed Sep 5, 2018
1 parent 80c2b83 commit 67e895e
Show file tree
Hide file tree
Showing 16 changed files with 847 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

@import 'filter-side-panel';
@import 'table-grid';
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.table-grid-pf {
.row,
[class*='col-'] {
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.table-grid-pf-body {
min-height: 50px;
position: relative;
width: 100%;

.row {
padding: 10px 0;
}
}

.table-grid-pf-head {
font-size: 12px;
padding: 10px 0;
}

.table-grid-pf-column-header {
align-items: center;
display: flex;
text-transform: uppercase;

.btn.btn-link {
color: initial;
overflow-x: hidden;
padding: 0;
text-overflow: ellipsis;
text-transform: uppercase;
white-space: nowrap;

&:hover,
&:focus {
outline: 0;
}
}

&.active-sort {
.btn.btn-link {
color: @link-color;
}
}
}

.table-grid-pf-header-sort-arrow {
margin-left: 10px;
}

&.bordered {
.table-grid-pf-head,
.table-grid-pf-body .row {
border-bottom: solid 1px #eee;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Patternfly React Extensions Partials
*/
@import 'filter-side-panel';
@import 'table-grid';
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.table-grid-pf {
.row,
[class*='col-'] {
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}

.table-grid-pf-body {
min-height: 50px;
position: relative;
width: 100%;

.row {
padding: 10px 0;
}
}

.table-grid-pf-head {
font-size: 12px;
padding: 10px 0;
}

.table-grid-pf-column-header {
align-items: center;
display: flex;
text-transform: uppercase;

.btn.btn-link {
color: initial;
overflow-x: hidden;
padding: 0;
text-overflow: ellipsis;
text-transform: uppercase;
white-space: nowrap;

&:hover,
&:focus {
outline: 0;
}
}

&.active-sort {
.btn.btn-link {
color: $link-color;
}
}
}

.table-grid-pf-header-sort-arrow {
margin-left: 10px;
}

&.bordered {
.table-grid-pf-head,
.table-grid-pf-body .row {
border-bottom: solid 1px #eee;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import TableGridHead from './TableGridHead';
import TableGridColumnHeader from './TableGridColumnHeader';
import TableGridBody from './TableGridBody';
import TableGridRow from './TableGridRow';

/**
* TableGrid Component for PatternFly
*/

const TableGrid = ({ children, className, bordered, ...props }) => {
const classes = classNames('table-grid-pf', { bordered }, className);
return (
<div className={classes} {...props}>
{children}
</div>
);
};

TableGrid.propTypes = {
/** Children nodes */
children: PropTypes.node,
/** Additional css classes */
className: PropTypes.string,
/** Flag to use a bordered grid */
bordered: PropTypes.bool
};
TableGrid.defaultProps = {
children: null,
className: '',
bordered: true
};

TableGrid.Head = TableGridHead;
TableGrid.ColumnHeader = TableGridColumnHeader;
TableGrid.Body = TableGridBody;
TableGrid.Row = TableGridRow;

export default TableGrid;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withInfo } from '@storybook/addon-info/dist/index';
import { defaultTemplate } from 'storybook/decorators/storyTemplates';
import { storybookPackageName, STORYBOOK_CATEGORY } from 'storybook/constants/siteConstants';
import { MockTableGridExample, MockTableGridExampleSource } from './_mocks_/mockTableGridExample';

import { TableGrid, TableGridHead, TableGridColumnHeader, TableGridBody, TableGridRow } from './index';

import { name } from '../../../package.json';
import { boolean, withKnobs } from '@storybook/addon-knobs';

const stories = storiesOf(`${storybookPackageName(name)}/${STORYBOOK_CATEGORY.CONTENT_VIEWS}/TableGrid`, module);

stories.addDecorator(
defaultTemplate({
title: 'Table Grid',
description:
'The TableGrid is based on the Bootstrap Grid Layout. The TableGridColumnHeaders should have the same ' +
'bootstrap col classes as the children of the TableGridRow component in order to maintain equal widths.'
})
);

stories.addDecorator(withKnobs);
stories.add(
'TableGrid',
withInfo({
source: false,
propTables: [TableGrid, TableGridHead, TableGridColumnHeader, TableGridBody, TableGridRow],
propTablesExclude: [MockTableGridExample],
text: (
<div>
<h1>Story Source</h1>
<pre>{MockTableGridExampleSource}</pre>
</div>
)
})(() => {
const bordered = boolean('Bordered', true);
return <MockTableGridExample bordered={bordered} />;
})
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { mount } from 'enzyme';
import { Grid, Icon, noop } from 'patternfly-react';

import { TableGrid } from './index';

test('TableGrid renders properly', () => {
const component = mount(
<TableGrid id="table-grid">
<TableGrid.Head>
<TableGrid.ColumnHeader id="title" sortable isSorted isAscending className="test-class">
Column 1
</TableGrid.ColumnHeader>
<TableGrid.ColumnHeader>Column 2</TableGrid.ColumnHeader>
<TableGrid.ColumnHeader sortable={false} isSorted={false} isAscending={false} onSortToggle={noop} />
<TableGrid.ColumnHeader sortable={false} isSorted={false} isAscending={false} onSortToggle={noop}>
<div>
<span>test 1</span>
<span>and two</span>
</div>
</TableGrid.ColumnHeader>
</TableGrid.Head>
<TableGrid.Body id="test-grid-body" className="test-grid-body">
<TableGrid.Row id="test-grid-row" className="test-grid-row">
<Grid.Col id="test-col-1" className="test-col1">
item 1 column 1
</Grid.Col>
<Grid.Col id="test-col-2" className="test-col2">
item 1 column 2
</Grid.Col>
<Grid.Col id="test-col-3" className="test-col3">
item 1 column 3
</Grid.Col>
<Grid.Col id="test-col-4" className="test-col4">
item 1 column 4
</Grid.Col>
</TableGrid.Row>
<TableGrid.Row id="test-grid-row-2">
<Grid.Col id="test-row-2-col-1">item 2 column 1</Grid.Col>
<Grid.Col id="two-children" className="test-col2">
<span>item 1</span>
<span>column 2</span>
</Grid.Col>
<Grid.Col id="icon-name" className="test-col3">
<Icon type="pf" name="error-circle-o" />
Danger
</Grid.Col>
<Grid.Col id="test-col-4" className="test-col4">
item 2 column 4
</Grid.Col>
</TableGrid.Row>
</TableGrid.Body>
</TableGrid>
);
expect(component.render()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

/**
* TableGridBody Component for PatternFly
*/

const TableGridBody = ({ children, className, ...props }) => {
const classes = classNames('table-grid-pf-body', className);
return (
<div className={classes} {...props}>
{children}
</div>
);
};

TableGridBody.propTypes = {
/** Children nodes */
children: PropTypes.node,
/** Additional css classes */
className: PropTypes.string
};
TableGridBody.defaultProps = {
children: null,
className: ''
};

export default TableGridBody;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Button, Grid, Icon, noop } from 'patternfly-react';

/**
* TableGridColumnHeader Component for PatternFly
*/

const TableGridColumnHeader = ({ children, className, sortable, isSorted, isAscending, onSortToggle, ...props }) => {
const classes = classNames(
'table-grid-pf-column-header text-nowrap',
{ 'active-sort': isSorted, descending: !isAscending },
className
);

return (
<Grid.Col className={classes} {...props}>
{sortable && (
<React.Fragment>
<Button bsStyle="link" onClick={onSortToggle}>
{children}
{isSorted && (
<Icon
className="table-grid-pf-header-sort-arrow"
type="pf"
name={isAscending ? 'sort-common-asc' : 'sort-common-desc'}
/>
)}
</Button>
</React.Fragment>
)}
{!sortable && children}
</Grid.Col>
);
};

TableGridColumnHeader.propTypes = {
/** Children nodes */
children: PropTypes.node,
/** Additional css classes */
className: PropTypes.string,
/** Flag if this column is sortable */
sortable: PropTypes.bool,
/** Flag if this is the current sort column */
isSorted: PropTypes.bool,
/** Flag if the sort is ascending */
isAscending: PropTypes.bool,
/** Callback function when the user click on this column header */
onSortToggle: PropTypes.func,
...Grid.Col.propTypes
};

TableGridColumnHeader.defaultProps = {
children: null,
className: '',
sortable: false,
isSorted: false,
isAscending: true,
onSortToggle: noop,
...Grid.Col.defaultProps
};

export default TableGridColumnHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Grid } from 'patternfly-react';

/**
* TableGridHead Component for PatternFly
*/

const TableGridHead = ({ children, className, ...props }) => {
const classes = classNames('table-grid-pf-head', className);
return (
<Grid.Row className={classes} {...props}>
{children}
</Grid.Row>
);
};

TableGridHead.propTypes = {
/** Children nodes */
children: PropTypes.node,
/** Additional css classes */
className: PropTypes.string
};
TableGridHead.defaultProps = {
children: null,
className: ''
};

export default TableGridHead;
Loading

0 comments on commit 67e895e

Please sign in to comment.