Skip to content

Commit

Permalink
chore(card): handle stretched link and disabled card
Browse files Browse the repository at this point in the history
  • Loading branch information
tonghauhive committed Jan 9, 2025
1 parent 1856c31 commit ee015cb
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 40 deletions.
52 changes: 26 additions & 26 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1280,11 +1280,11 @@ <h2>Selectable card</h2>
<div class="container">
<h2>Card</h2>
<div class="d-grid">
<sgds-card>
<sgds-card disabled>
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<h3 slot="title">Vertical Image Card</h3>
<span slot="subtitle">SUBTITLE</span>
<span slot="title">Vertical Image Card</span>
<span slot="description">default vertical card</span>
<sgds-link slot="link">
<a href="#">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
Expand All @@ -1293,17 +1293,17 @@ <h3 slot="title">Vertical Image Card</h3>
<sgds-card imageAdjustment="padding around">
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<h3 slot="title">Vertical Image Card</h3>
<span slot="subtitle">SUBTITLE</span>
<a href="#" slot="title"><span>Vertical Image Card</span></a>
<span slot="description">vertical card with image adjustment prop set to padding around</span>
<sgds-link slot="link">
<a href="#">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
</sgds-link>
<!-- <sgds-link slot="link"> -->
<a href="#" slot="link">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
<!-- </sgds-link> -->
</sgds-card>
<sgds-card imageAdjustment="aspect ratio">
<sgds-card imageAdjustment="aspect ratio" stretchedLink>
<img slot="image" alt="img alternate text goes here" width="467" height="300"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Image Card</h3>
<span slot="description">vertical card with image adjustment prop set to aspect ratio</span>
<sgds-link slot="link">
Expand All @@ -1313,17 +1313,17 @@ <h3 slot="title">Vertical Image Card</h3>
<sgds-card orientation="horizontal">
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Image Card</h3>
<span slot="description">horizontal card with card orientation set to horizontal</span>
<sgds-link slot="link">
<a href="#">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
</sgds-link>
<!-- <sgds-link slot="link"> -->
<a href="#" slot="link">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
<!-- </sgds-link> -->
</sgds-card>
<sgds-card orientation="horizontal" imagePosition="after">
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Image Card</h3>
<span slot="description">horizontal card with image position set to after</span>
<sgds-link slot="link">
Expand All @@ -1333,7 +1333,7 @@ <h3 slot="title">Horizontal Image Card</h3>
<sgds-card hideBorder>
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Image Card</h3>
<span slot="description">vertical card with no border</span>
<sgds-link slot="link">
Expand All @@ -1343,17 +1343,17 @@ <h3 slot="title">Vertical Image Card</h3>
<sgds-card orientation="horizontal" hideBorder>
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Image Card</h3>
<span slot="description">horizontal card with no border</span>
<sgds-link slot="link">
<a href="#">SM light dom anchor <sgds-icon name="arrow-right"></sgds-icon></a>
</sgds-link>
</sgds-card>
<sgds-card tinted>
<sgds-card tinted stretchedLink>
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Image Card</h3>
<span slot="description">vertical card with tinted background</span>
<sgds-link slot="link">
Expand All @@ -1363,7 +1363,7 @@ <h3 slot="title">Vertical Image Card</h3>
<sgds-card orientation="horizontal" tinted>
<img slot="image" alt="img alternate text goes here" width="467" height="312"
src="https://images.unsplash.com/photo-1473093295043-cdd812d0e601?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1740&amp;q=80">
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Image Card</h3>
<span slot="description">horizontal card with tinted background</span>
<sgds-link slot="link">
Expand All @@ -1372,7 +1372,7 @@ <h3 slot="title">Horizontal Image Card</h3>
</sgds-card>
<sgds-card>
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Icon Card</h3>
<span slot="description">default vertical card</span>
<sgds-link slot="link">
Expand All @@ -1381,7 +1381,7 @@ <h3 slot="title">Vertical Icon Card</h3>
</sgds-card>
<sgds-card orientation="horizontal">
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Icon Card</h3>
<span slot="description">horizontal card with card orientation set to horizontal</span>
<sgds-link slot="link">
Expand All @@ -1390,7 +1390,7 @@ <h3 slot="title">Horizontal Icon Card</h3>
</sgds-card>
<sgds-card hideBorder>
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Icon Card</h3>
<span slot="description">vertical card with no border</span>
<sgds-link slot="link">
Expand All @@ -1399,7 +1399,7 @@ <h3 slot="title">Vertical Icon Card</h3>
</sgds-card>
<sgds-card orientation="horizontal" hideBorder>
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Icon Card</h3>
<span slot="description">horizontal card with no border</span>
<sgds-link slot="link">
Expand All @@ -1408,7 +1408,7 @@ <h3 slot="title">Horizontal Icon Card</h3>
</sgds-card>
<sgds-card tinted>
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Vertical Icon Card</h3>
<span slot="description">vertical card with tinted background</span>
<sgds-link slot="link">
Expand All @@ -1417,7 +1417,7 @@ <h3 slot="title">Vertical Icon Card</h3>
</sgds-card>
<sgds-card orientation="horizontal" tinted>
<sgds-icon slot="icon" name="placeholder" size="3-xl"></sgds-icon>
<span slot="metadata">METADATA</span>
<span slot="subtitle">SUBTITLE</span>
<h3 slot="title">Horizontal Icon Card</h3>
<span slot="description">horizontal card with tinted background</span>
<sgds-link slot="link">
Expand Down
68 changes: 67 additions & 1 deletion src/base/card.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,35 @@
min-width: 0;
position: relative;
box-shadow: none;
transition: box-shadow 0.3s ease;
}

a.card {
text-decoration: none;
color: initial;
}

@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
}

.card.disabled {
opacity: var(--sgds-opacity-50);
cursor: not-allowed;
}

.card:not(.disabled):hover {
box-shadow: 0px 0px 1px 0px rgba(14, 14, 14, 0.12), 0px 8px 16px 0px rgba(14, 14, 14, 0.12);
}

a.card:focus {
outline: 0;
}

a.card:not(.disabled):focus-visible {
box-shadow: var(--sgds-box-shadow-focus);
}

.card-image {
Expand Down Expand Up @@ -77,12 +106,23 @@
margin-bottom: var(--sgds-margin-none);
}

slot[name="title"]::slotted(a) {
--sgds-link-color: var(--sgds-primary-color);
--sgds-font-size-2: var(--sgds-font-size-4);
--sgds-font-weight-regular: var(--sgds-font-weight-semibold);
color: var(--sgds-link-color);
font-size: var(--sgds-font-size-4);
font-weight: var(--sgds-font-weight-semibold);
text-decoration: none !important;
}

slot[name="description"]::slotted(*) {
color: var(--sgds-default-color-subtle);
}

slot[name="image"]::slotted(img) {
width: 100%;
display: block;
border-top-left-radius: calc(var(--sgds-border-radius-md) - var(--sgds-border-width-1));
border-top-right-radius: calc(var(--sgds-border-radius-md) - var(--sgds-border-width-1));
}
Expand All @@ -94,6 +134,32 @@ slot[name="image"]::slotted(img) {
}

slot[name="link"]::slotted(*) {
padding-top: var(--sgds-padding-sm);
margin-top: var(--sgds-padding-sm);
font-weight: 700;
}

slot[name="link"]::slotted(a) {
--sgds-link-color: var(--sgds-primary-color);
display: inline-flex;
gap: var(--sgds-gap-2-xs);
color: var(--sgds-link-color);
text-decoration: none !important;
}

slot[name="title"]::slotted(a:hover),
slot[name="title"]::slotted(a:focus),
slot[name="link"]::slotted(a:hover),
slot[name="link"]::slotted(a:focus) {
--sgds-link-color-emphasis: var(--sgds-primary-color-emphasis);
color: var(--sgds-link-color-emphasis);
}

slot[name="title"]::slotted(a:focus),
slot[name="link"]::slotted(a:focus) {
outline: 0;
}

slot[name="title"]::slotted(a:focus-visible),
slot[name="link"]::slotted(a:focus-visible) {
box-shadow: var(--sgds-box-shadow-focus);
}
2 changes: 1 addition & 1 deletion src/components/Card/card.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
gap: var(--sgds-gap-xs);
}

slot[name="metadata"]::slotted(*) {
slot[name="subtitle"]::slotted(*) {
--sgds-margin-2-xs: var(--sgds-margin-none);
--sgds-margin-xs: var(--sgds-margin-none);
--sgds-font-size-4: var(--sgds-font-size-1);
Expand Down
65 changes: 55 additions & 10 deletions src/components/Card/sgds-card.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { html } from "lit";
import { property, queryAssignedNodes } from "lit/decorators.js";
import { html, literal } from "lit/static-html.js";
import { property, query, queryAssignedNodes } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { CardElement } from "../../base/card-element";
import cardStyle from "./card.css";

Expand All @@ -10,20 +11,32 @@ export type CardOrientation = "vertical" | "horizontal";
/**
* @summary Cards can be used for headers and footers, a wide variety of content, contain contextual background colors and images.
* @slot image - Accepts an image or svg element of the card. Only a single element is allowed to be passed in.
* @slot metadata - The metadata of the card
* @slot subtitle - The subtitle of the card
* @slot title - The title of the card
* @slot description - The paragrapher text of the card
* @slot link - Accepts an anchor element. Only a single element is allowed to be passed in.
*/
export class SgdsCard extends CardElement {
static styles = [...CardElement.styles, cardStyle];

/** @internal */
@query("a.card") card: HTMLAnchorElement;

/** @internal */
@queryAssignedNodes({ slot: "image", flatten: true })
_imageNode!: Array<Node>;
/** @internal */
@queryAssignedNodes({ slot: "icon", flatten: true })
_iconNode!: Array<Node>;
/** @internal */
@queryAssignedNodes({ slot: "link", flatten: true })
_linkNode!: Array<Node>;

/** Extends the link passed in slot[name="link"] to the entire card */
@property({ type: Boolean, reflect: true }) stretchedLink = false;

/** Disables the card */
@property({ type: Boolean, reflect: true }) disabled = false;

/** Sets the orientation of the card */
@property({ type: String, reflect: true }) orientation: CardOrientation = "vertical";
Expand All @@ -43,28 +56,60 @@ export class SgdsCard extends CardElement {
const icon = this.shadowRoot.querySelector(".card-icon") as HTMLDivElement;
icon.style.display = "none";
}
if (this.disabled && this._linkNode.length > 0) {
const hyperlink = (this._linkNode[0] as HTMLLinkElement).querySelector("a");
hyperlink.setAttribute("disabled", "true");
hyperlink.removeAttribute("href");
}
}

handleTitleSlotChange(e: Event) {
const childNodes = (e.target as HTMLSlotElement).assignedNodes({ flatten: true }) as Array<HTMLElement>;

if (this.stretchedLink && childNodes[0] instanceof HTMLAnchorElement) {
const hyperlink = childNodes[0].querySelector("a") || childNodes[0];
hyperlink.removeAttribute("href");
}
return;
}

handleLinkSlotChange(e: Event) {
const childNodes = (e.target as HTMLSlotElement).assignedNodes({ flatten: true }) as Array<HTMLLinkElement>;
console.log(childNodes);
const childNodes = (e.target as HTMLSlotElement).assignedNodes({ flatten: true }) as
| Array<HTMLLinkElement>
| Array<HTMLAnchorElement>;

if (childNodes.length > 1) {
return console.error("Multiple elements passed into SgdsCard's link slot");
}

if (this.stretchedLink) {
const hyperlink = childNodes[0].querySelector("a") || childNodes[0];
this.card.setAttribute("href", hyperlink.href);
const linkSlot = this.shadowRoot.querySelector("slot[name='link']") as HTMLSlotElement;
linkSlot.style.display = "none";
}
return;
}

handleImgSlotChange(e: Event) {
const childNodes = (e.target as HTMLSlotElement).assignedNodes({ flatten: true }) as Array<HTMLOrSVGImageElement>;
console.log(childNodes);

if (childNodes.length > 1) {
return console.error("Multiple elements passed into SgdsCard's image slot");
}
}

render() {
const tag = this.stretchedLink ? literal`a` : literal`div`;
const cardTabIndex = !this.stretchedLink || this.disabled ? -1 : 0;

return html`
<div class="card">
<${tag}
class="card ${classMap({
disabled: this.disabled
})}"
tabindex=${cardTabIndex}
>
<div class="card-image">
<slot name="image" @slotchange=${this.handleImgSlotChange}></slot>
</div>
Expand All @@ -73,15 +118,15 @@ export class SgdsCard extends CardElement {
</div>
<div class="card-body">
<div class="card-header">
<slot name="metadata"></slot>
<h3 class="card-title"><slot name="title"></slot></h3>
<slot name="subtitle"></slot>
<h3 class="card-title"><slot name="title" @slotchange=${this.handleTitleSlotChange}></slot></h3>
</div>
<p class="card-text">
<slot name="description"></slot>
</p>
<slot name="link" @slotchange=${this.handleLinkSlotChange}></slot>
</div>
</div>
</${tag}>
`;
}
}
Expand Down
Loading

0 comments on commit ee015cb

Please sign in to comment.