diff --git a/packages/experimental/src/components/Card/Card.js b/packages/experimental/src/components/Card/Card.js index d0d436ca6a..824f0e4f32 100644 --- a/packages/experimental/src/components/Card/Card.js +++ b/packages/experimental/src/components/Card/Card.js @@ -6,9 +6,9 @@ import { pkgPrefix } from '../../global/js/settings'; export const Card = ({ actionIcon: ActionIcon, + caption, children, className, - href, label, media, mediaPosition, @@ -22,13 +22,16 @@ export const Card = ({ secondaryButtonText, title, }) => { - const cardClasses = cx({ - [`${pkgPrefix}-card`]: true, + const cardClasses = cx(`${pkgPrefix}-card`, { [`${pkgPrefix}-card--clickable`]: onClick, [`${pkgPrefix}-card--media-left`]: mediaPosition === 'left', className, }); + const headerClasses = cx(`${pkgPrefix}-card-header`, { + [`${pkgPrefix}-card-header--label-only`]: label && !title && !caption, + }); + const CardContent = (
{media &&
{media}
} @@ -38,19 +41,26 @@ export const Card = ({
)}
-
-

{label}

-

{title}

+
+ {label &&

{label}

} + {title &&

{title}

} + {caption &&

{caption}

}
{children}
{secondaryButtonText && ( - )} {primaryButtonText && ( - )} @@ -65,13 +75,7 @@ export const Card = ({
); - if (!href) return CardContent; - - return ( - - {CardContent} - - ); + return CardContent; }; Card.propTypes = { @@ -79,6 +83,10 @@ Card.propTypes = { * Icon to display in the bottom right of the card */ actionIcon: PropTypes.object, + /** + * Optional header caption + */ + caption: PropTypes.string, /** * Content that shows in the body of the card */ @@ -87,10 +95,6 @@ Card.propTypes = { * Optional user provided class */ className: PropTypes.string, - /** - * Providing an href turns the card into a clickable link - */ - href: PropTypes.string, /** * Optional label for the top of the card */ @@ -143,9 +147,9 @@ Card.propTypes = { Card.defaultProps = { actionIcon: null, + caption: '', children: '', className: '', - href: '', label: '', media: null, mediaPosition: 'top', diff --git a/packages/experimental/src/components/Card/Card.stories.js b/packages/experimental/src/components/Card/Card.stories.js index 1169b5759a..c67341a76f 100644 --- a/packages/experimental/src/components/Card/Card.stories.js +++ b/packages/experimental/src/components/Card/Card.stories.js @@ -6,10 +6,12 @@ // import React from 'react'; +import cx from 'classnames'; import { Card } from '.'; import styles from './_storybook-styles.scss'; // import index in case more files are added later. import mdx from './Card.mdx'; import { ArrowRight24, Cloud32 } from '@carbon/icons-react'; +import { AspectRatio } from 'carbon-components-react'; import { storybookPrefixCanary as storybookPrefix /* , storybookPrefixReleased */, } from '../../../config'; @@ -24,19 +26,24 @@ export default { }, }, argTypes: { - cards: { - defaultValue: 1, + columnSize: { + defaultValue: 'lg-4', control: { - type: 'range', - min: 1, - max: 4, - step: 1, + type: 'select', + options: ['sm-4', 'md-4', 'lg-4', 'max-4'], + }, + }, + mediaRatio: { + defaultValue: '1x1', + control: { + type: 'select', + options: ['16x9', '9x16', '2x1', '1x2', '4x3', '3x4', '1x1'], }, }, }, decorators: [ (Story) => ( -
+
), @@ -58,30 +65,61 @@ const defaultProps = { }; const Template = (opts) => { - const { children, cols, cards, ...args } = opts; - const cardsArray = []; - for (let i = 0; i < cards; i++) { - cardsArray.push( -
+ const { children, columnSize, ...args } = opts; + const colClasses = cx(`bx--col-${columnSize}`); + return ( +
+
{children}
- ); - } - return
{cardsArray.map((c) => c)}
; +
+ ); +}; + +const MediaTemplate = (opts) => { + const { children, columnSize, mediaRatio, ...args } = opts; + const colClasses = cx(`bx--col-${columnSize}`); + return ( +
+
+ {mediaRatio}} + {...args}> + {children} + +
+
+ ); }; export const Default = Template.bind({}); Default.args = { ...defaultProps, - media: img, }; -export const MediaLeft = Template.bind({}); +export const LabelOnly = Template.bind({}); +LabelOnly.args = { + ...defaultProps, + title: '', +}; + +export const WithCaption = Template.bind({}); +WithCaption.args = { + ...defaultProps, + caption: 'Description or long caption', + label: '', +}; + +export const WithMedia = MediaTemplate.bind({}); +WithMedia.args = { + ...defaultProps, +}; + +export const MediaLeft = MediaTemplate.bind({}); MediaLeft.args = { ...defaultProps, mediaPosition: 'left', - media: img, - cols: 8, + columnSize: 'md-4', }; export const WithActionIcon = Template.bind({}); @@ -97,12 +135,12 @@ WithPictogram.args = { pictogram: Cloud32, }; -export const WithSeondaryAction = Template.bind({}); -WithSeondaryAction.args = { +export const WithSecondaryAction = Template.bind({}); +WithSecondaryAction.args = { ...defaultProps, secondaryButtonText: 'Secondary', - secondaryButtonKind: 'secondary', - cols: 8, + secondaryButtonKind: 'ghost', + columnSize: 'md-4', }; export const ClickableCardWithOnclick = Template.bind({}); @@ -111,10 +149,3 @@ ClickableCardWithOnclick.args = { onClick: () => {}, primaryButtonText: '', }; - -export const ClickableCardWithLink = Template.bind({}); -ClickableCardWithLink.args = { - ...defaultProps, - href: '/', - primaryButtonText: '', -}; diff --git a/packages/experimental/src/components/Card/_card.scss b/packages/experimental/src/components/Card/_card.scss index 9992c9aff9..8fd5abf37a 100644 --- a/packages/experimental/src/components/Card/_card.scss +++ b/packages/experimental/src/components/Card/_card.scss @@ -9,6 +9,11 @@ .#{$pkg-prefix}-card--clickable { cursor: pointer; + transition: background $duration--fast-02; +} + +.#{$pkg-prefix}-card--clickable:hover { + background: $hover-ui; } .#{$pkg-prefix}-card--media-left { @@ -18,6 +23,7 @@ .#{$pkg-prefix}-card--media-left .#{$pkg-prefix}-card-content-container { display: flex; + flex: 1; flex-direction: column; } @@ -35,12 +41,28 @@ padding: $spacing-05; } +.#{$pkg-prefix}-card-header--label-only { + padding-bottom: $spacing-03; +} + +.#{$pkg-prefix}-card-header--label-only .#{$pkg-prefix}-card-label { + margin-bottom: 0; +} + .#{$pkg-prefix}-card-title { @include carbon--type-style('productive-heading-03'); } .#{$pkg-prefix}-card-label { @include carbon--type-style('label-01'); + + margin-bottom: $spacing-01; +} + +.#{$pkg-prefix}-card-caption { + @include carbon--type-style('caption-01'); + + margin-top: $spacing-01; } .#{$pkg-prefix}-card-body { diff --git a/packages/experimental/src/components/Card/_storybook-styles.scss b/packages/experimental/src/components/Card/_storybook-styles.scss index 9f9826a3cb..cfe1f5071d 100644 --- a/packages/experimental/src/components/Card/_storybook-styles.scss +++ b/packages/experimental/src/components/Card/_storybook-styles.scss @@ -1,4 +1,6 @@ @import './index'; +@import '../../global/styles/project-settings'; +@import '../../global/styles/carbon-settings'; // make the root full width to get a better idea of how the cards // look in a real grid situation @@ -6,3 +8,16 @@ #root { width: 100%; } + +// aspect ratio box styling +.card-story .bx--aspect-ratio { + display: flex; + align-items: center; + justify-content: center; + background: $ui-03; +} + +.#{$pkg-prefix}-card--media-left .#{$pkg-prefix}-card-media { + width: 100%; + max-width: 300px; +}