Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(table-grid): add Table Grid component #594

Merged
merged 1 commit into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@import 'variables';
@import 'filter-side-panel';
@import 'table-grid';
@import 'vertical-tabs';
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.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 {
color: @link-hover-color;
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 @@ -3,4 +3,5 @@
*/
@import 'variables';
@import 'filter-side-panel';
@import 'table-grid';
@import 'vertical-tabs';
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.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 {
color: $link-hover-color;
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,62 @@
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 && (
<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>
)}
{!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;
Loading