Standardize chip height (#213)

* make all chips the same size

* create DetailList, Detail components; clean up Chips, ChipGroup

* delete BasicChip in favor of <Chip isReadOnly>

* create our own ChipGroup to handle overflow
This commit is contained in:
Keith Grant
2019-05-28 08:49:03 -04:00
committed by GitHub
parent 189e12f8b3
commit 29e17ac49e
25 changed files with 1455 additions and 1050 deletions

View File

@@ -1,21 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Chip } from '@patternfly/react-core';
import './basicChip.scss';
const BasicChip = ({ children, onToggle, isOverflowChip }) => (
<Chip
className="awx-c-chip--basic"
onClick={onToggle}
isOverflowChip={isOverflowChip}
>
{children}
</Chip>
);
BasicChip.propTypes = {
children: PropTypes.node.isRequired,
};
export default BasicChip;

View File

@@ -1,18 +0,0 @@
.awx-c-chip--basic {
padding: 3px 8px;
height: 24px;
margin-right: 10px;
margin-bottom: 10px;
&.pf-c-chip {
margin-top: 0;
}
&.pf-m-overflow {
padding: 0;
}
&:not(.pf-m-overflow) .pf-c-button {
display: none;
}
}

View File

@@ -0,0 +1,18 @@
import { Chip } from '@patternfly/react-core';
import styled from 'styled-components';
export default styled(Chip)`
--pf-c-chip--m-read-only--PaddingTop: 3px;
--pf-c-chip--m-read-only--PaddingRight: 8px;
--pf-c-chip--m-read-only--PaddingBottom: 3px;
--pf-c-chip--m-read-only--PaddingLeft: 8px;
& > .pf-c-button {
padding: 3px 8px;
}
${props => (props.isOverflowChip && `
padding: 0;
`)}
`;

View File

@@ -0,0 +1,41 @@
import React, { useState } from 'react';
import { number } from 'prop-types';
import styled from 'styled-components';
import Chip from './Chip';
const ChipGroup = ({ children, className, showOverflowAfter, ...props }) => {
const [isExpanded, setIsExpanded] = useState(!showOverflowAfter);
const toggleIsOpen = () => setIsExpanded(!isExpanded);
const mappedChildren = React.Children.map(children, c => (
React.cloneElement(c, { component: 'li' })
));
const showOverflowToggle = showOverflowAfter && children.length > showOverflowAfter;
const numToShow = isExpanded
? children.length
: Math.min(showOverflowAfter, children.length);
const expandedText = 'Show Less';
const collapsedText = `${children.length - showOverflowAfter} more`;
return (
<ul className={`pf-c-chip-group ${className}`} {...props}>
{mappedChildren.slice(0, numToShow)}
{showOverflowToggle && (
<Chip isOverflowChip onClick={toggleIsOpen} component="li">
{isExpanded ? expandedText : collapsedText}
</Chip>
)}
</ul>
);
};
ChipGroup.propTypes = {
showOverflowAfter: number,
};
ChipGroup.defaultProps = {
showOverflowAfter: null,
};
export default styled(ChipGroup)`
--pf-c-chip-group--c-chip--MarginRight: 10px;
--pf-c-chip-group--c-chip--MarginBottom: 10px;
`;

View File

@@ -0,0 +1,2 @@
export { default as ChipGroup } from './ChipGroup';
export { default as Chip } from './Chip';

View File

@@ -0,0 +1,56 @@
import React, { Fragment } from 'react';
import { node, bool } from 'prop-types';
import { TextListItem, TextListItemVariants } from '@patternfly/react-core';
import styled from 'styled-components';
const DetailName = styled(({ fullWidth, ...props }) => (
<TextListItem {...props} />
))`
font-weight: var(--pf-global--FontWeight--bold);
text-align: right;
${props => props.fullWidth && `
grid-column: 1;
`}
`;
const DetailValue = styled(({ fullWidth, ...props }) => (
<TextListItem {...props} />
))`
word-break: break-all;
${props => props.fullWidth && `
grid-column: 2 / -1;
`}
`;
const Detail = ({ label, value, fullWidth }) => {
if (!value) return null;
return (
<Fragment>
<DetailName
component={TextListItemVariants.dt}
fullWidth={fullWidth}
>
{label}
</DetailName>
<DetailValue
component={TextListItemVariants.dd}
fullWidth={fullWidth}
>
{value}
</DetailValue>
</Fragment>
);
};
Detail.propTypes = {
label: node.isRequired,
value: node,
fullWidth: bool,
};
Detail.defaultProps = {
value: null,
fullWidth: false,
};
export default Detail;
export { DetailName };
export { DetailValue };

View File

@@ -0,0 +1,28 @@
import React from 'react';
import { TextList, TextListVariants } from '@patternfly/react-core';
import styled from 'styled-components';
const DetailList = ({ children, stacked, ...props }) => (
<TextList component={TextListVariants.dl} {...props}>
{children}
</TextList>
);
export default styled(DetailList)`
display: grid;
grid-gap: 20px;
${props => (props.stacked ? (`
grid-template-columns: auto 1fr;
`) : (`
--column-count: 1;
grid-template-columns: repeat(var(--column-count), auto minmax(10em, 1fr));
@media (min-width: 920px) {
--column-count: 2;
}
@media (min-width: 1210px) {
--column-count: 3;
}
`))}
`;

View File

@@ -0,0 +1,2 @@
export { default as DetailList } from './DetailList';
export { default as Detail, DetailName, DetailValue } from './Detail';

View File

@@ -5,7 +5,6 @@ import { SearchIcon } from '@patternfly/react-icons';
import {
Button,
ButtonVariant,
Chip,
InputGroup,
Modal,
} from '@patternfly/react-core';
@@ -17,6 +16,7 @@ import PaginatedDataList from '../PaginatedDataList';
import DataListToolbar from '../DataListToolbar';
import CheckboxListItem from '../ListItem';
import SelectedList from '../SelectedList';
import { ChipGroup, Chip } from '../Chip';
import { getQSConfig, parseNamespacedQueryString } from '../../util/qs';
class Lookup extends React.Component {
@@ -128,13 +128,13 @@ class Lookup extends React.Component {
const header = lookupHeader || i18n._(t`items`);
const chips = value ? (
<div className="pf-c-chip-group">
<ChipGroup>
{value.map(chip => (
<Chip key={chip.id} onClick={() => this.toggleSelected(chip)}>
{chip.name}
</Chip>
))}
</div>
</ChipGroup>
) : null;
return (

View File

@@ -1,40 +1,24 @@
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
Chip
} from '@patternfly/react-core';
import BasicChip from '../BasicChip/BasicChip';
import { Split as PFSplit, SplitItem } from '@patternfly/react-core';
import styled from 'styled-components';
import { ChipGroup, Chip } from '../Chip';
import VerticalSeparator from '../VerticalSeparator';
const selectedRowStyling = {
paddingTop: '15px',
paddingBottom: '5px',
borderLeft: '0',
borderRight: '0'
};
const Split = styled(PFSplit)`
padding-top: 15px;
padding-bottom: 5px;
border-bottom: #ebebeb var(--pf-global--BorderWidth--sm) solid;
align-items: baseline;
`;
const selectedLabelStyling = {
alignSelf: 'center',
fontSize: '14px',
fontWeight: 'bold'
};
const SplitLabelItem = styled(SplitItem)`
font-size: 14px;
font-weight: bold;
word-break: initial;
`;
class SelectedList extends Component {
constructor (props) {
super(props);
this.state = {
showOverflow: false
};
this.showOverflow = this.showOverflow.bind(this);
}
showOverflow = () => {
this.setState({ showOverflow: true });
};
render () {
const {
label,
@@ -44,58 +28,26 @@ class SelectedList extends Component {
displayKey,
isReadOnly
} = this.props;
const { showOverflow } = this.state;
const visibleItems = selected.slice(0, showOverflow ? selected.length : showOverflowAfter);
return (
<div className="awx-selectedList">
<div className="pf-l-split" style={selectedRowStyling}>
<div className="pf-l-split__item" style={selectedLabelStyling}>
{label}
</div>
<VerticalSeparator />
<div className="pf-l-split__item">
<div className="pf-c-chip-group">
{isReadOnly ? (
<Fragment>
{visibleItems
.map(selectedItem => (
<BasicChip
key={selectedItem.id}
>
{selectedItem[displayKey]}
</BasicChip>
))
}
</Fragment>
) : (
<Fragment>
{visibleItems
.map(selectedItem => (
<Chip
key={selectedItem.id}
onClick={() => onRemove(selectedItem)}
>
{selectedItem[displayKey]}
</Chip>
))
}
</Fragment>
)}
{(
!showOverflow
&& selected.length > showOverflowAfter
) && (
<Chip
isOverflowChip
onClick={() => this.showOverflow()}
>
{`${(selected.length - showOverflowAfter).toString()} more`}
</Chip>
)}
</div>
</div>
</div>
</div>
<Split>
<SplitLabelItem>
{label}
</SplitLabelItem>
<VerticalSeparator />
<SplitItem>
<ChipGroup showOverflowAfter={showOverflowAfter}>
{selected.map(item => (
<Chip
key={item.id}
isReadOnly={isReadOnly}
onClick={() => onRemove(item)}
>
{item[displayKey]}
</Chip>
))}
</ChipGroup>
</SplitItem>
</Split>
);
}
}

View File

@@ -1,22 +0,0 @@
.awx-selectedList {
--awx-selectedList--BackgroundColor: var(--pf-global--BackgroundColor--light-100);
--awx-selectedList--BorderColor: #ebebeb;
--awx-selectedList--BorderWidth: var(--pf-global--BorderWidth--sm);
--awx-selectedList--FontSize: var(--pf-c-chip__text--FontSize);
.pf-l-split {
padding-top: 20px;
padding-bottom: 10px;
border-bottom: var(--awx-selectedList--BorderWidth) solid var(--awx-selectedList--BorderColor);
}
.pf-l-split__item:first-child {
display: flex;
white-space: nowrap;
height: 30px;
}
.pf-c-chip {
margin-right: 10px;
margin-bottom: 10px;
}
}

View File

@@ -1,18 +1,19 @@
import React from 'react';
import styled from 'styled-components';
const Separator = styled.span`
display: inline-block;
width: 1px;
height: 30px;
margin-right: 20px;
margin-left: 20px;
background-color: #d7d7d7;
vertical-align: middle;
`;
const VerticalSeparator = () => (
<div>
<span style={{
content: '',
backgroundColor: '#d7d7d7',
width: '1px',
height: '30px',
display: 'inline-block',
verticalAlign: 'middle',
marginLeft: '20px',
marginRight: '20px'
}}
/>
<Separator />
</div>
);