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 10, 2023
1 parent b8fe9e0 commit cbdccd8
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 3 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.

165 changes: 164 additions & 1 deletion packages/cxl-ui/scss/cxl-card.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
:host {
display: block;
padding: var(--lumo-space-m);
padding: var(--lumo-space-m) var(--lumo-space-l);
margin-top: var(--lumo-space-m);
margin-bottom: var(--lumo-space-m);
overflow: hidden; // CSS columns @see https://stackoverflow.com/a/19348665/35946
Expand All @@ -10,6 +10,10 @@
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) {
Expand All @@ -32,6 +36,165 @@
background-color: var(--lumo-contrast);
}

/**
* CXL 2.0
*/

:host([theme~="cxl-course"]) {
position: relative;
margin-top: initial;
margin-bottom: initial;
height: max-content;
overflow: initial;
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-dashboard"][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.
*/
Expand Down
82 changes: 80 additions & 2 deletions packages/cxl-ui/src/components/cxl-card.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { customElement, property, state } from 'lit/decorators.js';
import '@conversionxl/cxl-lumo-styles';
import { registerGlobalStyles } from '@conversionxl/cxl-lumo-styles/src/utils';
import cxlCardGlobalStyles from '../styles/global/cxl-card-css.js';
Expand All @@ -11,8 +12,85 @@ export class CXLCardElement extends LitElement {
return [cxlCardStyles];
}

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` <slot></slot> `;
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>
`;
}
firstUpdated(_changedProperties) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { html } from 'lit';
import '@conversionxl/cxl-ui/src/components/cxl-card.js';
import '@conversionxl/cxl-lumo-styles';
import { CourseCardTemplate } from './template.js';
import { CXLCourseCard } from './[theme=cxl-course].stories.js';

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

const CXLCourseCard2 = CourseCardTemplate.bind({});
CXLCourseCard2.args = {
...CXLCourseCard.args,
new: true,
time: '2 days ago',
type: 'Video'
}

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)}
${CXLCourseCard(CXLCourseCard.args)}
${CXLCourseCard2(CXLCourseCard2.args)}
</section>
`;

export const CXLCourseCardDashboard = Template.bind({});
12 changes: 12 additions & 0 deletions packages/storybook/cxl-ui/cxl-card/[theme=cxl-course].stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CourseCardTemplate, args } from './template.js'
import '@conversionxl/cxl-ui/src/components/cxl-card.js';
import '@conversionxl/cxl-lumo-styles';

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


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

CXLCourseCard.args = args
35 changes: 35 additions & 0 deletions packages/storybook/cxl-ui/cxl-card/template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { html } from 'lit';

const renderTags = (tags, slot) => tags.map((tag, i) => html`${i > 0 ? html`<span slot=${slot}> | </span>` : ''}<span slot=${slot}>${tag}</span>`);

export const CourseCardTemplate = (course) => html`
<cxl-card
id=${course.id}
theme="cxl-course"
type=${course.type}
title=${course.title}
time=${course.time}
instructor=${course.instructor}
avatar-image=${course.avatarImage}
cta-url=${course.ctaUrl}
.new=${course.new}
>
${course.tags ? renderTags(course.tags, 'tags') : ''}
<p slot="content">${course.description}</p>
${course.contentTags ? renderTags(course.contentTags, 'content-tags') : ''}
<p slot="footer"> ${course.more}</p>
</cxl-card>
`;

export const args = {
id: 'cxl-course-1',
title: 'Account based marketing',
time: '3h 00min',
instructor: 'Tom Wesseling',
description: 'Master the strategies, tactics, metrics, and wisdom you need to become an ABM leader and accelerate the growth of your company and of your career.',
contentTags: ['B2B', 'campaigns', 'pilot planning'],
type: 'Course',
tags: ['Marketing', 'Analytics'],
avatarImage: 'https://cxl.com/institute/wp-content/uploads/2020/05/48192546_10156982340630746_8127333122065825792_n-wpv_400pxx400px_center_center.jpg',
more: "Lorem ipsum dolor sit amet consectetur adipisicing elit."
}

0 comments on commit cbdccd8

Please sign in to comment.