Skip to content

Commit

Permalink
feat(cxl-ui): implement dashboard card design
Browse files Browse the repository at this point in the history
  • Loading branch information
freudFlintstone committed Jul 11, 2023
1 parent d30c005 commit 383c3dd
Show file tree
Hide file tree
Showing 8 changed files with 388 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/cxl-lumo-styles/src/icons.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

197 changes: 197 additions & 0 deletions packages/cxl-ui/scss/cxl-course-card.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
:host {
display: block;
padding: var(--lumo-space-m) var(--lumo-space-l);
background: var(--lumo-tint);
border: 1px solid var(--lumo-contrast-10pct);
border-radius: var(--lumo-border-radius-s);
box-shadow: var(--lumo-box-shadow-xs);
break-inside: avoid;
transform: translateZ(0); // CSS columns @see https://stackoverflow.com/a/55110789/35946

.container {
display: none;
}
}

:host(:hover) {
border-color: var(--lumo-primary-color);
}

:host([hidden]) {
display: none;
}

:host(:first-child) {
margin-top: unset;
}

:host(:last-child) {
margin-bottom: unset;
}

:host([theme~="dark"]) {
background-color: var(--lumo-contrast);
}

/**
* CXL 2.0
*/

:host([theme~="cxl-course"]) {
position: relative;
height: max-content;
font-size: var(--lumo-font-size-s);

.container {
display: flex;
flex-direction: column;
gap: var(--lumo-space-s);
}

header {
display: flex;
align-items: start;
justify-content: space-between;
gap: var(--lumo-space-m);

.info {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--lumo-space-xs);
flex: 1 0 0;
align-self: stretch;
max-width: calc(100% - var(--lumo-space-m) - 80px);
overflow: hidden;

.title {
color: #1A1A1A;
font-size: var(--lumo-font-size-xl);
font-family: Roboto;
font-style: normal;
font-weight: 700;
line-height: var(--lumo-line-height-xs);
}

.attributes {
display: flex;
padding: var(--lumo-space-s) 0;
align-items: flex-start;
gap: var(--lumo-space-s);
align-self: stretch;
color: var(--lumo-shade-60pct);
}
}

.instructor-image {
height: 92px;
width: 80px;

img {
height: 80px;
border-radius: 100px;
overflow: hidden;
}
}

.tags span {
&:first-child, &.new {
color: var(--lumo-primary-color)
}
}
}

.tags {
display: flex;
gap: var(--lumo-space-s);
max-width: 100%;
overflow: hidden;

::slotted(span):not(:first-child) {
overflow: hidden;
text-overflow: ellipsis;
}
}

.content {
.tags {
::slotted(span) {
font-style: italic;
}
}
}

footer {
position: relative;

vaadin-details[theme="reverse"] {
&::part(summary) {
justify-content: flex-start;
gap: var(--lumo-space-s);
font-size: var(--lumo-font-size-s);
}

&::part(toggle) {
padding: calc(var(--lumo-space-xs) / 4);
margin-left: initial;
font-size: var(--lumo-font-size-m);
transform: rotate(90deg);
}

&[opened]::part(toggle) {
transform: rotate(-90deg);
}

&::part(summary-content) {
color: var(--lumo-contrast);
font-weight: bold;
}

&::part(content) {
padding-bottom: 0;
}
}

vaadin-button.cta {
position: absolute;
top: 0;
right: 0;
font-weight: bold;

vaadin-icon {
background: var(--lumo-primary-color-10pct);
border-radius: 100%;
margin-left: var(--lumo-space-xs);
height: var(--lumo-icon-size-s);
width: var(--lumo-icon-size-s);
padding: calc(var(--lumo-space-xs) / 2);
}
}
}

vaadin-icon.badge-new {
display: none;
}
}

:host([theme="cxl-course"][new]) {
vaadin-icon.badge-new {
display: block;
position: absolute;
top: calc(-1 * var(--lumo-space-s));
right: calc(-1 * var(--lumo-space-s));
height: calc(2 * var(--lumo-space-m));
width: calc(2 * var(--lumo-space-m));
background: var(--lumo-primary-color);
padding: 6px;
color: var(--lumo-primary-contrast-color);
border-radius: 100%;
}
}

/**
* Slots.
*/
::slotted(.entry-summary) {
font-family: var(--lumo-font-family);
}
92 changes: 92 additions & 0 deletions packages/cxl-ui/src/components/cxl-course-card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* eslint-disable import/no-extraneous-dependencies */
import { LitElement, html } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import cxlCourseCardStyles from '../styles/cxl-course-card-css.js';

@customElement('cxl-course-card')
export class CXLCourseCardElement extends LitElement {
static get styles() {
return [cxlCourseCardStyles];
}

separator = html`<span> | </span>`;

@state() _hasSlottedHeaderTags = false;

@property({ type: String }) id = '';

@property({ type: String }) type = 'Course';

@property({ type: String }) title = '';

@property({ type: String }) time = '';

@property({ type: String }) instructor = '';

@property({ type: String, attribute: 'avatar-image' }) avatarImage = '';

@property({ type: Boolean, reflect: true }) new = false;

@property({ type: String, attribute: 'cta-label' }) ctaLabel = 'View';

@property({ type: Boolean, attribute: 'cta-url' }) ctaUrl = false;

@property({ type: String, attribute: 'more' }) more = '';

_tagsSlotChanged (e) {
const slot = e.target
const children = slot.assignedNodes()
this._hasSlottedHeaderTags = !!children.length
}

render() {
return html`
<!-- Generic Slot, kept for backwards compatibility with current usage of theme="cxl-testimonial" and any other slotted content targeted by global styles -->
<slot></slot>
<div class="container">
<header>
<div class="info">
<div class="tags">
${this.type ? html`<span>${this.type}</span>`: ''}
${this.type && this._hasSlottedHeaderTags ? this.separator : ''}
<slot name="tags" @slotchange=${this._tagsSlotChanged}></slot>
${this.new ? html`${this.type ? this.separator : ''}<span class="new">NEW</span>` : '' }
</div>
<div class="title">
${this.title}
</div>
<div class="attributes">
<div class="time">
${this.type === 'Video' ? '' : html`<vaadin-icon icon="lumo:clock"></vaadin-icon>`}
${this.time}
</div>
<div class="instructor">
By: ${this.instructor}
</div>
</div>
</div>
<div class="instructor-image">
<img
src=${this.avatarImage}
alt="${this.instructor}"
/>
</div>
</header>
<section class="content">
<slot name="content"></slot>
<div class="tags">
<slot name="content-tags"></slot>
</div>
</section>
<footer>
<vaadin-details theme="reverse">
<div slot="summary">Read more</div>
<slot name="footer"></slot>
</vaadin-details>
<vaadin-button class="cta" theme="tertiary">${this.ctaLabel} ${this.type}<vaadin-icon icon="lumo:angle-right"></vaadin-icon> </vaadin-button>
</footer>
<vaadin-icon class="badge-new" icon="cxl:new"></vaadin-icon>
</div>
`;
}
}
1 change: 1 addition & 0 deletions packages/cxl-ui/src/index-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import * as Headroom from 'headroom.js';
// CXL.
export { CXLAppLayoutElement } from './components/cxl-app-layout.js';
export { CXLCardElement } from './components/cxl-card.js';
export { CXLCourseCardElement } from './components/cxl-course-card.js';
export { CXLCredentialElement } from './components/cxl-credential.js'
export { CXLCheckoutDetailsElement } from './components/cxl-checkout-details.js';
export { CXLMarketingNavElement } from './components/cxl-marketing-nav.js';
Expand Down
1 change: 1 addition & 0 deletions packages/cxl-ui/src/index-storybook.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Headroom from 'headroom.js';

export { CXLAppLayoutElement } from './components/cxl-app-layout.js';
export { CXLCardElement } from './components/cxl-card.js';
export { CXLCourseCardElement } from './components/cxl-course-card.js';
export { CXLMarketingNavElement } from './components/cxl-marketing-nav.js';
export { CXLSectionElement } from './components/cxl-section.js';
export { CXLStatsElement } from './components/cxl-stats.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { html } from 'lit';
import '@conversionxl/cxl-ui/src/components/cxl-course-card.js';
import '@conversionxl/cxl-lumo-styles';
import { CourseCardTemplate, args } from './template.js';
import { CXLCourseCard } from './[theme=cxl-course].stories.js';

export default {
title: 'CXL UI/cxl-course-card',
};

const CXLCourseCardNew = CourseCardTemplate.bind({});

CXLCourseCardNew.args = { ...args, new: true }

const CXLCourseCardVideo = CourseCardTemplate.bind({});

CXLCourseCardVideo.args = { ...args, type: 'Video', time: '2 days ago' }

const Template = () => html`
<style>
section {
display: grid;
grid: auto-flow / repeat(2, 1fr);
margin: 60px auto;
max-width: 900px;
grid-gap: var(--lumo-space-l);
padding: var(--lumo-space-l);
}
</style>
<section>
${CXLCourseCard(CXLCourseCard.args)}
${CXLCourseCard(CXLCourseCard.args)}
${CXLCourseCardNew(CXLCourseCardNew.args)}
${CXLCourseCardVideo(CXLCourseCardVideo.args)}
</section>
`;

export const CXLCourseCardDashboard = Template.bind({});

CXLCourseCardDashboard.args = {
numberOfCourses: 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CourseCardTemplate, args } from './template.js'
import '@conversionxl/cxl-ui/src/components/cxl-course-card.js';
import '@conversionxl/cxl-lumo-styles';

export default {
title: 'CXL UI/cxl-course-card',
parameters: {
layout: 'centered'
}
};


export const CXLCourseCard = CourseCardTemplate.bind({});

CXLCourseCard.args = args;
Loading

0 comments on commit 383c3dd

Please sign in to comment.