From 304143bc52d199cfd0167a873df0c48f284cf145 Mon Sep 17 00:00:00 2001 From: TheEarlyNerd Date: Fri, 5 Aug 2022 18:05:12 -0400 Subject: [PATCH] feat: added card actionIcon prop with 'dismiss' and 'overflow' --- .gitignore | 1 + src/Card/Card.scss | 7 ++ src/Card/CardActionIcon.jsx | 81 +++++++++++++++++++ src/Card/README.md | 2 +- src/Card/index.jsx | 12 ++- src/Card/tests/CardActionIcon.test.jsx | 18 +++++ .../CardActionIcon.test.jsx.snap | 75 +++++++++++++++++ 7 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 src/Card/CardActionIcon.jsx create mode 100644 src/Card/tests/CardActionIcon.test.jsx create mode 100644 src/Card/tests/__snapshots__/CardActionIcon.test.jsx.snap diff --git a/.gitignore b/.gitignore index 986dbca569..24e44a0f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .eslintcache +.prettierrc node_modules npm-debug.log coverage diff --git a/src/Card/Card.scss b/src/Card/Card.scss index 30232409e1..f1823faebb 100644 --- a/src/Card/Card.scss +++ b/src/Card/Card.scss @@ -86,6 +86,13 @@ } } +.pgn__card-close-container { + position: absolute; + z-index: 10; + top: .5rem; + inset-inline-end: .25rem; +} + .pgn__card-divider { border-top: 1px solid $card-divider-bg; height: 0; diff --git a/src/Card/CardActionIcon.jsx b/src/Card/CardActionIcon.jsx new file mode 100644 index 0000000000..7129f64d5b --- /dev/null +++ b/src/Card/CardActionIcon.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { IconButton, Icon } from '..'; +import { Close, MoreVert } from '../../icons'; + +const CardActionIcon = React.forwardRef( + ({ + className, + actionIcon, + onClick, + isActive, + variant, + }, ref) => { + if (actionIcon === 'overflow') { + return ( +
+ +
+ ); + } + return ( +
+ +
+ ); + }, +); + +CardActionIcon.propTypes = { + /** Specifies class name to append to the base element. */ + className: PropTypes.string, + /** Options for which type of actionIcon the Card will use. */ + actionIcon: PropTypes.oneOf(['overflow', 'dismiss']), + /** Click handler for the button */ + onClick: PropTypes.func, + /** whether to show the `IconButton` in an active state, whose styling is distinct from default state */ + isActive: PropTypes.bool, + /** The visual style of the dialog box */ + variant: PropTypes.oneOf(['default', 'warning', 'danger', 'success', 'dark']), +}; + +CardActionIcon.defaultProps = { + className: undefined, + actionIcon: 'dismiss', + onClick: () => {}, + isActive: false, + variant: 'dark', +}; + +export default CardActionIcon; diff --git a/src/Card/README.md b/src/Card/README.md index 8d273472ee..5c78d83a3a 100644 --- a/src/Card/README.md +++ b/src/Card/README.md @@ -32,7 +32,7 @@ This component uses a `Card` from react-bootstrap as a base component and extend const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth }); return ( - + ( @@ -28,7 +31,10 @@ const Card = React.forwardRef(({ })} ref={ref} tabIndex={isClickable ? '0' : '-1'} - /> + > + {actionIcon ? : undefined} + {children} + )); @@ -37,6 +43,7 @@ export { default as CardDeck } from 'react-bootstrap/CardDeck'; export { default as CardImg } from 'react-bootstrap/CardImg'; export { default as CardGroup } from 'react-bootstrap/CardGroup'; export { default as CardGrid } from './CardGrid'; +export { default as CardActionIcon } from './CardActionIcon'; Card.propTypes = { ...BaseCard.propTypes, @@ -46,6 +53,8 @@ Card.propTypes = { orientation: PropTypes.oneOf(['vertical', 'horizontal']), /** Specifies whether the `Card` is clickable, if `true` appropriate `hover` and `focus` styling will be added. */ isClickable: PropTypes.bool, + /** Optional interactive icon positioned in the top right of the card. */ + actionIcon: PropTypes.oneOf(['overflow', 'dismiss']), /** Specifies loading state. */ isLoading: PropTypes.bool, /** Specifies whether to display `Card` in muted styling. */ @@ -58,6 +67,7 @@ Card.defaultProps = { orientation: 'vertical', isClickable: false, muted: false, + actionIcon: undefined, isLoading: false, }; diff --git a/src/Card/tests/CardActionIcon.test.jsx b/src/Card/tests/CardActionIcon.test.jsx new file mode 100644 index 0000000000..207fcaba58 --- /dev/null +++ b/src/Card/tests/CardActionIcon.test.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import CardActionIcon from '../CardActionIcon'; + +describe('', () => { + it('renders without props', () => { + const tree = renderer.create(( + + )).toJSON(); + expect(tree).toMatchSnapshot(); + }); + it('renders with "overflow" option for actionIcon prop', () => { + const tree = renderer.create(( + + )).toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/Card/tests/__snapshots__/CardActionIcon.test.jsx.snap b/src/Card/tests/__snapshots__/CardActionIcon.test.jsx.snap new file mode 100644 index 0000000000..dd3b294ce7 --- /dev/null +++ b/src/Card/tests/__snapshots__/CardActionIcon.test.jsx.snap @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders with "overflow" option for actionIcon prop 1`] = ` +
+ +
+`; + +exports[` renders without props 1`] = ` +
+ +
+`;