Skip to content

Commit

Permalink
feat: allow slotted title for card
Browse files Browse the repository at this point in the history
Co-authored-by: Westbrook Johnson <westbrook.johnson@gmail.com>
  • Loading branch information
msdewey committed Feb 5, 2020
1 parent 4179f10 commit aaf7157
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 4 deletions.
4 changes: 3 additions & 1 deletion __snapshots__/card.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
<div id="body">
<div id="header">
<div id="title">
Card Title
<slot name="title">
Card Title
</slot>
</div>
</div>
<div id="content">
Expand Down
12 changes: 12 additions & 0 deletions packages/card/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ yarn add @spectrum-web-components/card
</sp-card>
```

## Title

The default application of a title for an `sp-card` is to leverage the `title` attribute. When HTML based title content is desired, the `title` slot is also available for deliverin this content.

```html demo
<sp-card subtitle="JPG">
<h1 slot="title">Card Title</h1>
<img slot="cover-photo" src="https://picsum.photos/200/300" />
<div slot="footer">Footer</div>
</sp-card>
```

## Variants

There are multiple card variants to choose from in Spectrum. The `variant`
Expand Down
19 changes: 16 additions & 3 deletions packages/card/src/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import cardStyles from './card.css.js';

/**
* @slot preview - This is the preview image for Gallery Cards
* @slot title - HTML content to be listed as the title
* @slot cover-photo - This is the cover photo for Default and Quiet Cards
* @slot description - A description of the card
* @slot footer - Footer text
Expand All @@ -40,12 +41,22 @@ export class Card extends LitElement {
@property()
public subtitle = '';

protected get renderTitle(): TemplateResult {
return html`
<div id="title">
<slot name="title">
${this.title}
</slot>
</div>
`;
}

protected renderGallery(): TemplateResult {
return html`
<slot name="preview"></slot>
<div id="body">
<div id="header">
<div id="title">${this.title}</div>
${this.renderTitle}
<div id="subtitle">${this.subtitle}</div>
<slot name="description"></slot>
</div>
Expand All @@ -57,7 +68,9 @@ export class Card extends LitElement {
return html`
<slot name="preview"></slot>
<div id="body">
<div id="header"><div id="title">${this.title}</div></div>
<div id="header">
${this.renderTitle}
</div>
<div id="content">
<div id="subtitle">${this.subtitle}</div>
<slot name="description"></slot>
Expand All @@ -71,7 +84,7 @@ export class Card extends LitElement {
<slot name="cover-photo" id="cover-photo"></slot>
<div id="body">
<div id="header">
<div id="title">${this.title}</div>
${this.renderTitle}
</div>
<div id="content">
<div id="subtitle">${this.subtitle}</div>
Expand Down
18 changes: 18 additions & 0 deletions packages/card/stories/card.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { html, TemplateResult } from 'lit-html';

import '../';
import { landscape, portrait } from './images';
import '../../textfield';

export default {
component: 'sp-card',
Expand Down Expand Up @@ -58,3 +59,20 @@ export const Quiet = (): TemplateResult => {
</div>
`;
};

export const SlottedTitle = (): TemplateResult => {
return html`
<div
style="color: var(--spectrum-global-color-gray-800); --spectrum-card-body-header-height: auto;"
>
<sp-card subtitle="JPG">
<sp-textfield
slot="title"
placeholder="Enter Title"
></sp-textfield>
<img slot="cover-photo" src=${portrait} alt="Demo Image" />
<div slot="footer">Footer</div>
</sp-card>
</div>
`;
};
52 changes: 52 additions & 0 deletions packages/card/test/card.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,56 @@ describe('card', () => {

expect(el).shadowDom.to.equalSnapshot();
});
it('displays the `title` attribute as `#title`', async () => {
const testTitle = 'This is a test title';
const el = await fixture<Card>(
html`
<sp-card title=${testTitle} subtitle="JPG">
<img slot="preview" src="https://picsum.photos/532/192" />
<div slot="footer">Footer</div>
</sp-card>
`
);

await elementUpdated(el);

const root = el.shadowRoot ? el.shadowRoot : el;
const titleEl = root.querySelector('#title');

expect(titleEl, 'did not find title element').to.not.be.null;
expect((titleEl as HTMLDivElement).textContent).to.contain(
testTitle,
'the title renders in the element'
);
});
it('displays the slotted content as `#title`', async () => {
const testTitle = 'This is a test title';
const el = await fixture<Card>(
html`
<sp-card subtitle="JPG">
<h1 slot="title">${testTitle}</h1>
<img slot="preview" src="https://picsum.photos/532/192" />
<div slot="footer">Footer</div>
</sp-card>
`
);

await elementUpdated(el);

const root = el.shadowRoot ? el.shadowRoot : el;
const titleSlot = root.querySelector(
'[name="title"]'
) as HTMLSlotElement;

expect(titleSlot, 'did not find slot element').to.not.be.null;
const nodes = titleSlot.assignedNodes();
const h1Element = nodes.find(
(node) => (node as HTMLElement).tagName === 'H1'
);
expect(h1Element, 'did not find H1 element').to.not.be.null;
expect((h1Element as HTMLHeadingElement).textContent).to.contain(
testTitle,
'the slotted content renders in the element'
);
});
});
1 change: 1 addition & 0 deletions test/visual/stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = [
'card--default',
'card--gallery',
'card--quiet',
'card--slotted-title',
'checkbox--default',
'checkbox--checked',
'checkbox--indeterminate',
Expand Down

0 comments on commit aaf7157

Please sign in to comment.