Skip to content

Commit

Permalink
feat(card): added pictogram (#4746)
Browse files Browse the repository at this point in the history
### Related Ticket(s)

#4447

### Description

Added the abillity to use pictograms on `Card`.

Added a new story and knobs to test this functionality.
  • Loading branch information
raphaelamadeu-zz authored Dec 23, 2020
1 parent 5ac10f3 commit 9e322f4
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 32 deletions.
3 changes: 2 additions & 1 deletion packages/styles/scss/components/card/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@
:host(#{$dds-prefix}-card-cta-footer),
:host(#{$dds-prefix}-feature-card-footer),
:host(#{$dds-prefix}-feature-cta-footer) {
margin-top: auto; /* Moves the footer down to the bottom in the card */
margin-top: auto;
/* Moves the footer down to the bottom in the card */

.#{$prefix}--card__cta__copy {
margin-right: $carbon--spacing-03;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,42 @@ import '@carbon/ibmdotcom-web-components/es/components/card/card.js';
</dds-card>
```

## Card with pictogram
```html
<dds-card
color-scheme=${inverse ? 'inverse' : ''}
pictogram-placement="${pictogramPlacement}"
href="https://example.com"
>
<span slot="eyebrow">Eyebrow text</span>
<span slot="heading">Lorem ipsum dolor</span>
<p>Copy to be shown on hover if the pictogram placement is bottom</p>
<svg
slot="pictogram"
focusable="false"
preserveAspectRatio="xMidYMid meet"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
data-autoid="dds--card__pictogram"
aria-label="Pictogram description"
width="48"
height="48"
viewBox="0 0 48 48"
role="img"
class="bx--card__pictogram"
>
<path
fill="none"
stroke-linejoin="round"
stroke-miterlimit="10"
stroke-width=".72"
d="M37,32 H11c-1.1,0-2-0.9-2-2V13c0-1.1,0.9-2,2-2h26c1.1,
0,2,0.9,2,2v17C39,31.1,38.1,32,37,32z M17,37h14 M24,32v5 M9,27h30"
></path>
</svg>
</dds-card>
```

## Props

<Props of="dds-card" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ifNonNull from 'carbon-web-components/es/globals/directives/if-non-null';
import readme from './README.stories.mdx';
import textNullable from '../../../../.storybook/knob-text-nullable';
import '../card';
import { PICTOGRAM_PLACEMENT } from '../defs';

export const Default = ({ parameters }) => {
const { image, href, alt, defaultSrc, eyebrow, heading, copy, inverse, footer, iconPlacement } = parameters?.props?.Card ?? {};
Expand Down Expand Up @@ -45,6 +46,53 @@ const iconPlacement = {
right: 'right',
};

const pictogramPlacements = {
[PICTOGRAM_PLACEMENT.TOP]: PICTOGRAM_PLACEMENT.TOP,
[PICTOGRAM_PLACEMENT.BOTTOM]: PICTOGRAM_PLACEMENT.BOTTOM,
};

export const Pictogram = ({ parameters }) => {
const { href, heading, copy, pictogramPlacement, eyebrow, inverse } = parameters?.props?.PictogramCard ?? {};
return html`
<dds-card
color-scheme=${inverse ? 'inverse' : ''}
pictogram-placement="${pictogramPlacement}"
href=${ifNonNull(href || undefined)}
>
<span slot="eyebrow">${eyebrow}</span>
<span slot="heading">${heading}</span>
${copy
? html`
<p>${copy}</p>
`
: ``}
<svg
slot="pictogram"
focusable="false"
preserveAspectRatio="xMidYMid meet"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
data-autoid="dds--card__pictogram"
aria-label="Pictogram description"
width="48"
height="48"
viewBox="0 0 48 48"
role="img"
class="bx--card__pictogram"
>
<path
fill="none"
stroke-linejoin="round"
stroke-miterlimit="10"
stroke-width=".72"
d="M37,32 H11c-1.1,0-2-0.9-2-2V13c0-1.1,0.9-2,2-2h26c1.1,
0,2,0.9,2,2v17C39,31.1,38.1,32,37,32z M17,37h14 M24,32v5 M9,27h30"
></path>
</svg>
</dds-card>
`;
};

export default {
title: 'Components/Card',
decorators: [
Expand All @@ -70,6 +118,23 @@ export default {
footer: textNullable('Footer copy text (footer.copy)', 'Card CTA text', groupId),
iconPlacement: select('Footer icon placement (footer.iconPlacement)', iconPlacement, iconPlacement.right, groupId),
}),
PictogramCard: ({ groupId }) => ({
href: textNullable('Card Href (href):', 'https://example.com', groupId),
heading: textNullable('Card Heading (heading):', 'Lorem ipsum dolor sit amet', groupId),
eyebrow: textNullable('Card Eyebrow (eyebrow):', 'Eyebrow text', groupId),
copy: textNullable(
'Card Copy (copy):',
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
groupId
),
pictogramPlacement: select(
'Card pictogram placement (card.pictogramPlacement)',
pictogramPlacements,
pictogramPlacements.top,
groupId
),
inverse: boolean('inverse', false, groupId),
}),
},
},
};
44 changes: 44 additions & 0 deletions packages/web-components/src/components/card/card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,47 @@
color: $inverse-link;
}
}

:host(#{$dds-prefix}-card)[pictogram-placement='bottom']:hover {
::slotted(svg[slot='pictogram']) {
display: none;
}

.#{$prefix}--card__copy {
display: flex;
margin-bottom: 0;
}
}

:host(#{$dds-prefix}-card) {
.#{$prefix}--card__pictogram {
display: flex;

.#{$prefix}--card__heading {
margin-bottom: 0;
flex: 1;
display: flex;
align-items: flex-end;
}
}

&[pictogram-placement='bottom'] {
.#{$prefix}--card__pictogram {
.#{$prefix}--card__heading {
align-items: flex-start;
}
}

.#{$prefix}--card__copy {
display: none;
}
}

::slotted(svg[slot='pictogram']) {
color: $icon-01;
}

&[color-scheme='inverse'] ::slotted(svg[slot='pictogram']) {
color: $inverse-link;
}
}
78 changes: 67 additions & 11 deletions packages/web-components/src/components/card/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import StableSelectorMixin from '../../globals/mixins/stable-selector';
import DDSLink from '../link/link';
import DDSCardFooter from './card-footer';
import styles from './card.scss';
import { PICTOGRAM_PLACEMENT } from './defs';

const { prefix } = settings;
const { stablePrefix: ddsPrefix } = ddsSettings;
Expand All @@ -26,6 +27,7 @@ const slotExistencePropertyNames = {
eyebrow: '_hasEyebrow',
heading: '_hasHeading',
image: '_hasImage',
pictogram: '_hasPictogram',
};

/**
Expand Down Expand Up @@ -63,15 +65,25 @@ class DDSCard extends StableSelectorMixin(DDSLink) {
@internalProperty()
protected _hasCopy = false;

/**
* `true` if there is a pictogram.
*/
@internalProperty()
protected _hasPictogram = false;

/**
* Handles `slotchange` event.
*/
protected _handleSlotChange({ target }: Event) {
const { name } = target as HTMLSlotElement;
const hasContent = (target as HTMLSlotElement)
.assignedNodes()
.some(node => node.nodeType !== Node.TEXT_NODE || node!.textContent!.trim());
this[slotExistencePropertyNames[name] || '_hasCopy'] = hasContent;
const { pictogramPlacement: currentPictogramPlacement } = this;
const { dataset, name } = target as HTMLSlotElement;
const { pictogramPlacement } = dataset;
if (!pictogramPlacement || pictogramPlacement === currentPictogramPlacement) {
const hasContent = (target as HTMLSlotElement)
.assignedNodes()
.some(node => node.nodeType !== Node.TEXT_NODE || node!.textContent!.trim());
this[slotExistencePropertyNames[name] || '_hasCopy'] = hasContent;
}
}

/**
Expand Down Expand Up @@ -109,18 +121,56 @@ class DDSCard extends StableSelectorMixin(DDSLink) {
* @returns The inner content.
*/
protected _renderInner() {
const { _hasEyebrow: hasEyebrow, _hasHeading: hasHeading, _handleSlotChange: handleSlotChange } = this;
const {
_hasEyebrow: hasEyebrow,
_hasHeading: hasHeading,
_handleSlotChange: handleSlotChange,
_hasPictogram: hasPictogram,
} = this;
return html`
${this._renderImage()}
<div class="${prefix}--card__wrapper">
<div class="${prefix}--card__wrapper ${hasPictogram ? `${prefix}--card__pictogram` : ''}">
<div class="${prefix}--card__content">
<p ?hidden="${!hasEyebrow}" class="${prefix}--card__eyebrow">
<slot name="eyebrow" @slotchange="${handleSlotChange}"></slot>
</p>
<h3 ?hidden="${!hasHeading}" class="${prefix}--card__heading">
<slot name="heading" @slotchange="${handleSlotChange}"></slot>
</h3>
${this._renderCopy()}
${this.pictogramPlacement === PICTOGRAM_PLACEMENT.TOP
? html`
<slot
name="pictogram"
data-pictogram-placement="${PICTOGRAM_PLACEMENT.TOP}"
@slotchange="${handleSlotChange}"
></slot>
`
: ''}
${this.pictogramPlacement !== PICTOGRAM_PLACEMENT.TOP || !hasPictogram
? html`
<h3 ?hidden="${!hasHeading}" class="${prefix}--card__heading">
<span>
<slot name="heading" @slotchange="${handleSlotChange}"></slot>
</span>
</h3>
`
: null}
${this.pictogramPlacement === PICTOGRAM_PLACEMENT.BOTTOM || !hasPictogram ? this._renderCopy() : ''}
${this.pictogramPlacement === PICTOGRAM_PLACEMENT.BOTTOM
? html`
<slot
name="pictogram"
data-pictogram-placement="${PICTOGRAM_PLACEMENT.BOTTOM}"
@slotchange="${handleSlotChange}"
></slot>
`
: ''}
${hasPictogram && this.pictogramPlacement === PICTOGRAM_PLACEMENT.TOP
? html`
<h3 ?hidden="${!hasHeading}" class="${prefix}--card__heading">
<span>
<slot name="heading" @slotchange="${handleSlotChange}"></slot>
</span>
</h3>
`
: null}
<slot name="footer"></slot>
</div>
</div>
Expand All @@ -140,6 +190,12 @@ class DDSCard extends StableSelectorMixin(DDSLink) {
@property()
href = '';

/**
* Pictogram placement
*/
@property({ attribute: 'pictogram-placement', reflect: true })
pictogramPlacement = PICTOGRAM_PLACEMENT.TOP;

createRenderRoot() {
return this.attachShadow({
mode: 'open',
Expand Down
21 changes: 21 additions & 0 deletions packages/web-components/src/components/card/defs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @license
*
* Copyright IBM Corp. 2020
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

export enum PICTOGRAM_PLACEMENT {
/**
* Top pictogram
*/
TOP = 'top',
/**
* Bottom pictogram
*/
BOTTOM = 'bottom',
}

export default PICTOGRAM_PLACEMENT;
22 changes: 18 additions & 4 deletions packages/web-components/tests/snapshots/dds-card-cta.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@
<slot name="eyebrow">
</slot>
</p>
<slot
data-pictogram-placement="top"
name="pictogram"
>
</slot>
<h3
class="bx--card__heading"
hidden=""
>
<slot name="heading">
</slot>
<span>
<slot name="heading">
</slot>
</span>
</h3>
<div
class="bx--card__copy"
Expand Down Expand Up @@ -57,12 +64,19 @@
<slot name="eyebrow">
</slot>
</p>
<slot
data-pictogram-placement="top"
name="pictogram"
>
</slot>
<h3
class="bx--card__heading"
hidden=""
>
<slot name="heading">
</slot>
<span>
<slot name="heading">
</slot>
</span>
</h3>
<div class="bx--card__copy">
<slot>
Expand Down
Loading

0 comments on commit 9e322f4

Please sign in to comment.