From aa1d3fc98c04a95f513e027b3b4660483147181e Mon Sep 17 00:00:00 2001 From: Boaz Shuster Date: Tue, 18 Dec 2018 05:43:56 +0200 Subject: [PATCH] feat(Chip): Add the Chip component to PF4 Signed-off-by: Boaz Shuster --- .../react-core/src/components/Chip/Chip.d.ts | 20 +++ .../src/components/Chip/Chip.docs.js | 15 ++ .../react-core/src/components/Chip/Chip.js | 69 ++++++++ .../src/components/Chip/Chip.test.js | 54 ++++++ .../src/components/Chip/ChipButton.d.ts | 7 + .../src/components/Chip/ChipButton.js | 30 ++++ .../Chip/__snapshots__/Chip.test.js.snap | 158 ++++++++++++++++++ .../components/Chip/examples/SimpleChip.js | 42 +++++ .../react-core/src/components/Chip/index.d.ts | 1 + .../react-core/src/components/Chip/index.js | 1 + .../react-core/src/components/index.ts | 1 + 11 files changed, 398 insertions(+) create mode 100644 packages/patternfly-4/react-core/src/components/Chip/Chip.d.ts create mode 100644 packages/patternfly-4/react-core/src/components/Chip/Chip.docs.js create mode 100644 packages/patternfly-4/react-core/src/components/Chip/Chip.js create mode 100644 packages/patternfly-4/react-core/src/components/Chip/Chip.test.js create mode 100644 packages/patternfly-4/react-core/src/components/Chip/ChipButton.d.ts create mode 100644 packages/patternfly-4/react-core/src/components/Chip/ChipButton.js create mode 100644 packages/patternfly-4/react-core/src/components/Chip/__snapshots__/Chip.test.js.snap create mode 100644 packages/patternfly-4/react-core/src/components/Chip/examples/SimpleChip.js create mode 100644 packages/patternfly-4/react-core/src/components/Chip/index.d.ts create mode 100644 packages/patternfly-4/react-core/src/components/Chip/index.js diff --git a/packages/patternfly-4/react-core/src/components/Chip/Chip.d.ts b/packages/patternfly-4/react-core/src/components/Chip/Chip.d.ts new file mode 100644 index 00000000000..8d6b0f98862 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/Chip.d.ts @@ -0,0 +1,20 @@ +import { SFC, HTMLProps } from 'react'; +import { Omit, OneOf } from '../../typeUtils'; +import { TooltipPosition } from '../Tooltip'; + +export const ChipVariant = { + overflow: 'overflow', + closable: 'closable' +}; + +export interface ChipProps extends Omit, 'children' > { + children: string; + isOverflowed?: boolean; + variant: OneOf; + position: OneOf; +} + +declare const Chip: SFC; + +export default Chip; + diff --git a/packages/patternfly-4/react-core/src/components/Chip/Chip.docs.js b/packages/patternfly-4/react-core/src/components/Chip/Chip.docs.js new file mode 100644 index 00000000000..66a02d24103 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/Chip.docs.js @@ -0,0 +1,15 @@ +import { Chip } from '@patternfly/react-core'; +import SimpleExample from './examples/SimpleChip'; + +export default { + title: 'Chip', + components: { + Chip, + }, + examples: [ + { + component: SimpleExample, + title: 'Simple Example' + } + ] +}; diff --git a/packages/patternfly-4/react-core/src/components/Chip/Chip.js b/packages/patternfly-4/react-core/src/components/Chip/Chip.js new file mode 100644 index 00000000000..0d4ea6ece88 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/Chip.js @@ -0,0 +1,69 @@ +import React from 'react'; +import { css } from '@patternfly/react-styles'; +import PropTypes from 'prop-types'; +import ChipButton from './ChipButton'; +import { Tooltip, TooltipPosition } from '../Tooltip'; +import { TimesCircleIcon } from '@patternfly/react-icons'; +import styles from '@patternfly/patternfly-next/components/Chip/chip.css'; +import { getUniqueId } from '../../internal/util'; + +export const ChipVariant = { + overflow: 'overflow', + closable: 'closable' +}; + +const Chip = ({ variant, onClick, children, id, position, className, ...props }) => { + const idChip = id || getUniqueId() + switch (variant) { + case ChipVariant.overflow: + return ( +
+ + {children} + +
+ ); + default: + const ChipComponent = ( +
+ + {children} + + + +
+ ); + return children.length < 16 ? ( + ChipComponent + ) : ( + + {ChipComponent} + + ); + } +}; + +Chip.propTypes = { + /** Content rendered inside the chip text */ + children: PropTypes.string.isRequired, + /** ID of the chip */ + id: PropTypes.string, + /** Additional classes added to the chip item */ + className: PropTypes.string, + /** Builds the chip structure according to variant */ + variant: PropTypes.oneOf(Object.values(ChipVariant)), + /** Position of the tooltip which is displayed if text is longer */ + position: PropTypes.oneOf(Object.values(TooltipPosition)), + /** Function that is called when clicking on the chip button */ + onClick: PropTypes.func +}; + +Chip.defaultProps = { + id: undefined, + className: '', + position: 'top', + variant: ChipVariant.closable +}; + +export default Chip; diff --git a/packages/patternfly-4/react-core/src/components/Chip/Chip.test.js b/packages/patternfly-4/react-core/src/components/Chip/Chip.test.js new file mode 100644 index 00000000000..33728f93686 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/Chip.test.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import ChipButton from './ChipButton'; +import Chip from './Chip'; + +test('ChipButton', () => { + const view = shallow( + + Close + + ); + expect(view).toMatchSnapshot(); +}); + +describe('Chip', () => { + test('overflow', () => { + const view = shallow( + + 4 more + + ); + expect(view).toMatchSnapshot(); + }); + + test('closable', () => { + const view = shallow( + + Chip + + ); + expect(view).toMatchSnapshot(); + }); + + + test('closable with tooltip', () => { + const view = shallow( + + 12345678901234567891 + + ); + expect(view).toMatchSnapshot(); + }); + + test('onClick', () => { + const clickFnc = jest.fn(); + const view = shallow( + clickFnc('chip_one')} id="chip_one"> + Chip + + ); + view.find(ChipButton).simulate('click'); + expect(clickFnc).toBeCalledWith('chip_one'); + }); +}); diff --git a/packages/patternfly-4/react-core/src/components/Chip/ChipButton.d.ts b/packages/patternfly-4/react-core/src/components/Chip/ChipButton.d.ts new file mode 100644 index 00000000000..c6f800a0f35 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/ChipButton.d.ts @@ -0,0 +1,7 @@ +import { SFC, HTMLProps } from 'react'; + +export interface ChipButtonProps extends HTMLProps {} + +declare const ChipButton: SFC; + +export default ChipButton; diff --git a/packages/patternfly-4/react-core/src/components/Chip/ChipButton.js b/packages/patternfly-4/react-core/src/components/Chip/ChipButton.js new file mode 100644 index 00000000000..035d68592b8 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/ChipButton.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { css } from '@patternfly/react-styles'; +import PropTypes from 'prop-types'; +import styles from '@patternfly/patternfly-next/components/Chip/chip.css'; +import { Button } from '../Button'; + +const ChipButton = ({ children, className, onClick, ...props }) => { + return ( + + ); +}; + +ChipButton.propTypes = { + /** Content rendered inside the chip item */ + children: PropTypes.node, + /** Additional classes added to the chip item */ + className: PropTypes.string, + /** Function that is called when clicking on the chip button */ + onClick: PropTypes.func, +}; + +ChipButton.defaultProps = { + children: null, + className: '', + onClick: () => {} +}; + +export default ChipButton; diff --git a/packages/patternfly-4/react-core/src/components/Chip/__snapshots__/Chip.test.js.snap b/packages/patternfly-4/react-core/src/components/Chip/__snapshots__/Chip.test.js.snap new file mode 100644 index 00000000000..2469986787b --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/__snapshots__/Chip.test.js.snap @@ -0,0 +1,158 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Chip closable 1`] = ` +.pf-c-chip__text { + display: block; + max-width: 7.5rem; + overflow: hidden; + font-size: 0.75rem; + color: #282d33; + text-overflow: ellipsis; + white-space: nowrap; +} +.pf-c-chip.my-chp-cls { + display: inline-flex; + position: relative; + align-items: center; + padding-left: 0.5rem; + background-color: #ffffff; + border-radius: 3px; +} + +
+ + Chip + + + +
+`; + +exports[`Chip closable with tooltip 1`] = ` +.pf-c-chip__text { + display: block; + max-width: 7.5rem; + overflow: hidden; + font-size: 0.75rem; + color: #282d33; + text-overflow: ellipsis; + white-space: nowrap; +} +.pf-c-chip.my-chp-cls { + display: inline-flex; + position: relative; + align-items: center; + padding-left: 0.5rem; + background-color: #ffffff; + border-radius: 3px; +} + + +
+ + 12345678901234567891 + + + +
+
+`; + +exports[`Chip overflow 1`] = ` +.pf-c-chip__text { + display: block; + max-width: 7.5rem; + overflow: hidden; + font-size: 0.75rem; + color: #282d33; + text-overflow: ellipsis; + white-space: nowrap; +} +.pf-c-chip.pf-m-overflow.my-chp-cls { + display: inline-flex; + position: relative; + align-items: center; + padding-left: 0.5rem; + background-color: #ffffff; + border-radius: 3px; +} + +
+ + + 4 more + + +
+`; + +exports[`ChipButton 1`] = ` + +`; diff --git a/packages/patternfly-4/react-core/src/components/Chip/examples/SimpleChip.js b/packages/patternfly-4/react-core/src/components/Chip/examples/SimpleChip.js new file mode 100644 index 00000000000..1c802ae07ee --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/examples/SimpleChip.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { Chip } from '@patternfly/react-core'; + +class SimpleChip extends React.Component { + state = { + show: ['chip_one', 'chip_two'] + }; + deleteItem = id => { + const { show } = this.state; + const ix = show.indexOf(id); + if (ix < 0) { + return; + } + this.setState(() => ({ + show: [...show.slice(0, ix), ...show.slice(ix + 1, show.length)] + })); + }; + render() { + const { show } = this.state + return ( + + {show.includes('chip_one') && ( + this.deleteItem('chip_one')}> + Chip + + )} +
+
+ {show.includes('chip_two') && ( + this.deleteItem('chip_two')}> + Really long Chip that goes on and on + + )} +
+
+ 4 more +
+ ); + } +} + +export default SimpleChip; diff --git a/packages/patternfly-4/react-core/src/components/Chip/index.d.ts b/packages/patternfly-4/react-core/src/components/Chip/index.d.ts new file mode 100644 index 00000000000..68faf22289c --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/index.d.ts @@ -0,0 +1 @@ +export { default as Chip } from './Chip'; diff --git a/packages/patternfly-4/react-core/src/components/Chip/index.js b/packages/patternfly-4/react-core/src/components/Chip/index.js new file mode 100644 index 00000000000..68faf22289c --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/Chip/index.js @@ -0,0 +1 @@ +export { default as Chip } from './Chip'; diff --git a/packages/patternfly-4/react-core/src/components/index.ts b/packages/patternfly-4/react-core/src/components/index.ts index fcf4c029366..858e7879a4f 100644 --- a/packages/patternfly-4/react-core/src/components/index.ts +++ b/packages/patternfly-4/react-core/src/components/index.ts @@ -10,6 +10,7 @@ export * from './Breadcrumb'; export * from './Button'; export * from './Card'; export * from './Checkbox'; +export * from './Chip'; export * from './DataList'; export * from './Dropdown'; export * from './EmptyState';