Skip to content

Commit

Permalink
feat(chipGroup): Add Chip Group component to pf4 (#1245)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibolton336 authored and dlabaj committed Feb 11, 2019
1 parent bb2c768 commit d3f2cc9
Show file tree
Hide file tree
Showing 27 changed files with 470 additions and 116 deletions.
15 changes: 0 additions & 15 deletions packages/patternfly-4/react-core/src/components/Chip/Chip.docs.js

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { OneOf } from '../../typeUtils';
import { TooltipPosition } from '../Tooltip';

export interface ChipProps extends HTMLProps<HTMLDivElement> {
badgeText?: string;
children?: string;
closeBtnAriaLabel: string;
isOverflowChip: boolean;
isBadge: boolean;
tooltipPosition: OneOf<typeof TooltipPosition, keyof typeof TooltipPosition>;
}

declare const Chip: FunctionComponent<ChipProps>;

export default Chip;

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Chip extends React.Component {
if (this.state.isTooltipVisible) {
return (
<Tooltip position={tooltipPosition} content={children}>
<div className={css(styles.chip, className)}>
<li className={css(styles.chip, className)}>
<span ref={this.span} className={css(styles.chipText)} id={randomId}>
{children}
</span>
Expand All @@ -45,12 +45,12 @@ class Chip extends React.Component {
>
<TimesCircleIcon aria-hidden="true" />
</ChipButton>
</div>
</li>
</Tooltip>
);
}
return (
<div className={css(styles.chip, className)}>
<li className={css(styles.chip, className)}>
<span ref={this.span} className={css(styles.chipText)} id={randomId}>
{children}
</span>
Expand All @@ -62,44 +62,38 @@ class Chip extends React.Component {
>
<TimesCircleIcon aria-hidden="true" />
</ChipButton>
</div>
</li>
);
};

render() {
const { isOverflowChip } = this.props;
return (
<GenerateId>
{randomId => (
<React.Fragment>{isOverflowChip ? this.renderOverflowChip() : this.renderChip(randomId)}</React.Fragment>
)}
</GenerateId>
<GenerateId>{randomId => (isOverflowChip ? this.renderOverflowChip() : this.renderChip(randomId))}</GenerateId>
);
}
}
Chip.propTypes = {
/** Content rendered inside the chip text */
children: PropTypes.string,
children: PropTypes.node,
/** Aria Label for close button */
closeBtnAriaLabel: PropTypes.string,
/** ID of the chip */
id: PropTypes.string,
/** Additional classes added to the chip item */
className: PropTypes.string,
/** Flag indicating if the chip has overflow */
isOverflowChip: PropTypes.bool,
/** Position of the tooltip which is displayed if text is longer */
tooltipPosition: PropTypes.oneOf(Object.values(TooltipPosition)),
/** Function that is called when clicking on the chip button */
onClick: PropTypes.func
onClick: PropTypes.func,
/** Position of the tooltip which is displayed if text is longer */
tooltipPosition: PropTypes.oneOf(Object.values(TooltipPosition))
};

Chip.defaultProps = {
id: undefined,
children: null,
closeBtnAriaLabel: 'close',
className: '',
tooltipPosition: 'top',
isOverflowChip: false
isOverflowChip: false,
tooltipPosition: 'top'
};

export default Chip;
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('ChipButton', () => {
describe('Chip', () => {
test('overflow', () => {
const view = shallow(
<Chip className="my-chp-cls" isOverflowChip={true}>
<Chip className="my-chp-cls" isOverflowChip>
4 more
</Chip>
);
Expand All @@ -31,13 +31,12 @@ describe('Chip', () => {
expect(view).toMatchSnapshot();
});


test('closable with tooltip', () => {
const view = shallow(
<Chip className="my-chp-cls" id="chip_one">
12345678901234567891
1234567890123456789
</Chip>
);
expect(view).toMatchSnapshot();
});
})
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ReactNode, HTMLProps } from 'react';

export interface ChipGroupProps extends HTMLProps<HTMLDivElement> {
children: ReactNode;
collapsedText?: string;
expandedText?: string;
withToolbar?: boolean;
}

declare const ChipGroup: React.ComponentClass<ChipGroupProps>;

export default ChipGroup;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ChipGroup, ChipGroupToolbarItem, Chip } from '@patternfly/react-core';
import Toolbar from './examples/ToolbarChipGroup';
import MultiSelect from './examples/MultiSelectChipGroup';
import BadgeChip from './examples/BadgeChip';

export default {
title: 'ChipGroup',
components: {
ChipGroup,
ChipGroupToolbarItem,
Chip
},
examples: [
{
component: Toolbar,
title: 'Chip Group Toolbar'
},
{
component: MultiSelect,
title: 'Chip Group Multi-Select'
},
{
component: BadgeChip,
title: 'Badge Chip Group'
}
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import { css } from '@patternfly/react-styles';
import PropTypes from 'prop-types';
import styles from '@patternfly/patternfly/components/ChipGroup/chip-group.css';
import { Chip } from '@patternfly/react-core';
import { fillTemplate } from '../../helpers';

class ChipGroup extends React.Component {
state = {
isOpen: false
};

toggleCollapse = () => {
this.setState(prevState => ({
isOpen: !prevState.isOpen
}));
};

renderToolbarGroup() {
const { isOpen } = this.state;
return <InnerChipGroup {...this.props} isOpen={isOpen} onToggleCollapse={this.toggleCollapse} />;
}

renderChipGroup() {
const { className } = this.props;
const { isOpen } = this.state;
return (
<div className={css(styles.chipGroup, className)}>
<InnerChipGroup {...this.props} isOpen={isOpen} onToggleCollapse={this.toggleCollapse} />
</div>
);
}

render() {
const { withToolbar, children } = this.props;
if (React.Children.count(children)) {
return withToolbar ? this.renderToolbarGroup() : this.renderChipGroup();
}
return null;
}
}

const InnerChipGroup = props => {
const { children, expandedText, isOpen, onToggleCollapse, collapsedText } = props;

const collapsedTextResult = fillTemplate(collapsedText, { remaining: React.Children.count(children) - 1 });
return (
<React.Fragment>
{isOpen ? (
<React.Fragment>{children}</React.Fragment>
) : (
<React.Fragment>
{React.Children.map(children, (child, i) => {
if (i === 0) return child;
})}
</React.Fragment>
)}
{React.Children.count(children) > 1 && (
<Chip isOverflowChip onClick={onToggleCollapse}>
{isOpen ? expandedText : collapsedTextResult}
</Chip>
)}
</React.Fragment>
);
};

ChipGroup.propTypes = {
/** Content rendered inside the chip text */
children: PropTypes.node,
/** Additional classes added to the chip item */
className: PropTypes.string,
/** Customizable "Show Less" text string */
expandedText: PropTypes.string,
/**
* Customizeable template string. Use variable "${remaining}" for the overflow chip count.
*/
collapsedText: PropTypes.string,
/** Flag for grouping with a toolbar & category name */
withToolbar: PropTypes.bool
};

ChipGroup.defaultProps = {
children: null,
className: '',
expandedText: 'Show Less',
collapsedText: '${remaining} more',
withToolbar: false
};

export default ChipGroup;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import { Chip, ChipGroup, ChipGroupToolbarItem } from './index';

describe('ChipGroup', () => {
test('chip group default', () => {
const view = shallow(
<ChipGroup>
<Chip>1.1</Chip>
</ChipGroup>
);

expect(view).toMatchSnapshot();
});

test('chip group with toolbar', () => {
const view = shallow(
<ChipGroup withToolbar>
<ChipGroupToolbarItem>
<Chip>1.1</Chip>
</ChipGroupToolbarItem>
</ChipGroup>
);
expect(view).toMatchSnapshot();
});

test('chip group expanded', () => {
const view = mount(
<ChipGroup>
<Chip>1</Chip>
<Chip>2</Chip>
</ChipGroup>
);
const overflowButton = view.find('.pf-m-overflow .pf-c-chip__text');
expect(overflowButton.text()).toBe('1 more');
overflowButton.simulate('click');
expect(overflowButton.text()).toBe('Show Less');
});

test('chip group will not render if no children passed', () => {
const view = shallow(<ChipGroup />);
expect(view.equals(null)).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SFC, HTMLProps, ReactNode } from 'react';

export interface ChipGroupToolbarItemProps extends HTMLProps<HTMLDivElement> {
categoryName?: string;
}

declare const ChipGroupToolbarItem: SFC<ChipGroupToolbarItemProps>;

export default ChipGroupToolbarItem;
Loading

0 comments on commit d3f2cc9

Please sign in to comment.