Skip to content

Commit

Permalink
fix(vwc-calendar): cells wrong grid columns (#862)
Browse files Browse the repository at this point in the history
* fix(vwc-calendar): cells wrong grid columns

* add lit-html dep

* simplified naming
  • Loading branch information
yinonov authored May 27, 2021
1 parent 2a2bf11 commit 1f77e91
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 53 deletions.
1 change: 1 addition & 0 deletions components/calendar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"dependencies": {
"@vonage/vvd-core": "2.9.0",
"lit-element": "^2.4.0",
"lit-html": "^1.3.0",
"tslib": "^2.0.3"
},
"devDependencies": {
Expand Down
15 changes: 15 additions & 0 deletions components/calendar/src/_vwc-calendar-variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// snap fraction within an hour
$fraction: 4;
// number of columns according to days of week
$total-columns: 7;
// the rows according to hours a day
$total-rows: 24;


// event variables
$color: --vvd-calendar-event--primary-color;
$day: --vvd-calendar-event--day;
$start: --vvd-calendar-event--start;
$duration: --vvd-calendar-event--duration;
$indent: --vvd-calendar-event--indent;
$overlap-count: --vvd-calendar-event--overlap-count;
39 changes: 27 additions & 12 deletions components/calendar/src/vwc-calendar-event.scss
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
$indent: --vvd-calendar-event-indent;
$overlap-count: --vvd-calendar-event-overlap-count;
$event-color: --vvd-calendar-event-event-color;
$event-day: --vvd-calendar-event-event-day;
$event-row: --vvd-calendar-event-event-row;
@use '@vonage/vvd-typography/scss/typography';
@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/scheme-variables';
@use 'vwc-calendar-variables' as calendar-variables;

:host {
display: contents;
}

section {
#{$indent}: calc(var(#{$overlap-count}, 0) * 8px);
z-index: var(#{$overlap-count});
margin: 1px 1px 1px calc(1px + var(#{$indent}));
background-color: var(#{$event-color});
border-radius: 3.64752px;
grid-column: var(#{$event-day});
grid-row: var(#{$event-row});
#{calendar-variables.$indent}: calc(var(#{calendar-variables.$overlap-count}, 0) * 8px);
z-index: var(#{calendar-variables.$overlap-count});
overflow: hidden;
padding: 16px;
margin: 1px 1px 1px calc(1px + var(#{calendar-variables.$indent}));
background-color: var(#{calendar-variables.$color}, var(#{scheme-variables.$vvd-color-neutral-40}));
border-radius: 6px;
color: var(#{scheme-variables.$vvd-color-on-primary});
contain: strict;
grid-column: var(#{calendar-variables.$day});
grid-row: var(#{calendar-variables.$start}) / span var(#{calendar-variables.$duration});
&:focus {
z-index: 2000;
}
}

h2 {
@include typography.typography-cat-shorthand('body-2-bold');
margin: 0 0 4px;
> strong {
font: inherit;
}
}

p {
@include typography.typography-cat-shorthand('caption');
margin: 0;
}
60 changes: 52 additions & 8 deletions components/calendar/src/vwc-calendar-event.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import '@vonage/vvd-core';
import {
customElement, html, LitElement, property, TemplateResult, unsafeCSS
customElement, html, LitElement, property, TemplateResult
} from 'lit-element';
import { style } from './vwc-calendar-event.css';
import { styleMap } from 'lit-html/directives/style-map';

declare global {
interface HTMLElementTagNameMap {
Expand All @@ -23,31 +24,74 @@ export class VWCCalendarEvent extends LitElement {
static styles = [style];

/**
* @prop the label of the event
* @prop the heading of the event
* @public
* */
@property({ type: String, reflect: true })
label?: string;
@property({ type: String, reflect: false })
heading?: string;

/**
* @prop the description of the event
* @public
* */
@property({ type: String, reflect: false })
description?: string;

/**
* @prop day - day of the week (starts from 0)
* @public
* */
@property({ type: Number, reflect: true })
day?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
@property({ type: Number, reflect: false })
day: 1 | 2 | 3 | 4 | 5 | 6 | 7 = 1;

/**
* @prop color - color of event card
* @public
* */
@property({ type: String, reflect: false })
color?: string;

/**
* @prop sets card display precendence and indentation
* @public
* */
@property({ type: String, reflect: false, attribute: 'overlap-count' })
overlapCount?: string;

/**
* @prop start - time of day event starts
* @public
* */
@property({ type: Number, reflect: false })
start = 0; // TODO should be converted to allowed range

/**
* @prop duration - event's time duration in hours
* @public
* */
@property({ type: Number, reflect: false })
duration = 1; // TODO should be converted to allowed range

/**
* the html markup
* @internal
* */
protected render(): TemplateResult {
const styles = {
...this.color && { '--vvd-calendar-event--primary-color': this.color },
...this.overlapCount && { '--vvd-calendar-event--overlap-count': this.overlapCount },
'--vvd-calendar-event--start': (this.start + 1).toString(),
'--vvd-calendar-event--duration': (this.duration).toString(),
'--vvd-calendar-event--day': this.day.toString()
};
return html`
<section
role="button"
tabindex="0"
style="--vvd-calendar-event-event-day: ${unsafeCSS(this.day)}"
style="${styleMap(styles)}"
>
<label>${this.label}</label>
<h2><strong>${this.heading}</strong></h2>
<p>${this.description}</p>
</section>
`;
}
Expand Down
46 changes: 21 additions & 25 deletions components/calendar/src/vwc-calendar.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@use 'vwc-calendar-variables' as calendar-variables;
@use '@vonage/vvd-design-tokens/build/scss/semantic-variables/scheme-variables';
@use '@vonage/vvd-typography/scss/typography';

Expand All @@ -7,13 +8,6 @@ ol {
list-style: none;
}

// snap fraction within an hour
$fraction: 4;
// the rows according to hours a day
$total-rows: 24;
// number of columns according to days of week
$total-columns: 7;

.container {
display: grid;
width: max(100%, 500px);
Expand All @@ -27,7 +21,7 @@ $total-columns: 7;
.time {
display: grid;
grid-area: time;
grid-template-rows: repeat($total-rows, 1fr);
grid-template-rows: repeat(calendar-variables.$total-rows, 1fr);
margin-inline-end: 15px;
> li {
display: flex;
Expand All @@ -46,32 +40,30 @@ $total-columns: 7;
.headline {
display: grid;
grid-area: headline;
grid-template-columns: repeat($total-columns, 1fr);
grid-template-columns: repeat(calendar-variables.$total-columns, 1fr);
> li > time {
@include typography.typography-cat-shorthand('caption');
text-transform: uppercase;
}
}

.calendar {
$sum: $total-rows * $total-columns;
$next: 1;
display: grid;
overflow: hidden;
background-color: var(#{scheme-variables.$vvd-color-neutral-20});
border-radius: 3.64752px;
background-color: var(#{scheme-variables.$vvd-color-neutral-20}, rgb(128, 128, 128));
border-radius: 6px;
box-shadow: 0 0 3.64752px rgba(0, 0, 0, 0.15);
counter-reset: listing;
gap: 1px;
grid-area: calendar;
grid-auto-flow: column;
grid-template: repeat($total-rows * $fraction, 1fr) / repeat(
$total-columns,
grid-template: repeat(calendar-variables.$total-rows * calendar-variables.$fraction, 1fr) / repeat(
calendar-variables.$total-columns,
1fr
);
> [role="listitem"i] {
height: 35px;
background-color: var(#{scheme-variables.$vvd-color-base});
background-color: var(#{scheme-variables.$vvd-color-base}, rgb(255, 255, 255));
grid-column: var(--column);
grid-row: var(--row);
&::before {
Expand All @@ -83,19 +75,23 @@ $total-columns: 7;
}
}

@for $i from 1 through $total-rows {
$current-row: $i * $fraction - $fraction + 1;
[role="listitem"i]:nth-child(#{$total-rows}n + #{$i}) {
--row: #{$current-row} / span #{$fraction};
@for $i from 1 through calendar-variables.$total-rows {
$current-row: $i * calendar-variables.$fraction - calendar-variables.$fraction + 1;
[role="listitem"i]:nth-child(#{calendar-variables.$total-rows}n + #{$i}) {
--row: #{$current-row} / span #{calendar-variables.$fraction};
}
}
@for $i from 1 through $total-columns {
$sum: $sum - $total-rows + 1;
[role="listitem"i]:nth-child(1n + #{$next}):nth-last-child(1n + #{$sum}) {

@for $i from 1 through calendar-variables.$total-columns {
/* extra 2 for the sibling events wrapper and the self containment */
$total-cells: calendar-variables.$total-columns * calendar-variables.$total-rows + 2;

$from: $i * calendar-variables.$total-rows - calendar-variables.$total-rows + 1;
$less: $total-cells - $i * calendar-variables.$total-rows;

[role="listitem"i]:nth-child(1n + #{$from}):nth-last-child(1n + #{$less}) {
--column: #{$i};
}
/* stylelint-disable-next-line order/order */
$next: $next + $total-rows;
}
}

Expand Down
6 changes: 3 additions & 3 deletions components/calendar/src/vwc-calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class VWCCalendar extends LitElement {
datetime?: Date;

#daysLength = 7;
#hoursOfDay = (Array.from({ length: 23 }) as Date[])
#hours = (Array.from({ length: 23 }) as Date[])
.fill(new Date(new Date().setHours(0, 0, 0)))
.map((d, i) => new Date(d.setHours(++i)))

Expand Down Expand Up @@ -102,7 +102,7 @@ export class VWCCalendar extends LitElement {

protected renderTimeCells(): TemplateResult[] {
const templates = [];
for (let i = 0; i < (this.#hoursOfDay.length + 1) * this.#daysLength; i++) {
for (let i = 0; i < (this.#hours.length + 1) * this.#daysLength; i++) {
templates.push(html`<div role="listitem" tabindex="0"></div>`);
}
return templates;
Expand Down Expand Up @@ -133,7 +133,7 @@ export class VWCCalendar extends LitElement {
<ol class="time">
<!-- TODO: align to convention of generation from first hour in day and a length of hours. -->
<!-- TODO: get styled hour and datetime value -->
${this.#hoursOfDay.map(h => html`<li>
${this.#hours.map(h => html`<li>
<time datetime="${this.formatDate(h, { hour: 'numeric', minute: 'numeric', hour12: false })}">
${this.formatDate(h, { hour: 'numeric', hour12: true })}
</time>
Expand Down
12 changes: 7 additions & 5 deletions components/calendar/stories/calendar.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ export default {
};

const Template = args => html`<vwc-calendar ...=${spread(args)}>
<vwc-calendar-event day="2" style="--vvd-calendar-event-event-color: #4cc3d2; --vvd-calendar-event-event-row: 9 / span 24; --vvd-calendar-event-overlap-count: 2"></vwc-calendar-event>
<vwc-calendar-event day="2" style="--vvd-calendar-event-event-color: #d6219c; --vvd-calendar-event-event-row: 5 / span 16"></vwc-calendar-event>
<vwc-calendar-event day="2" style="--vvd-calendar-event-event-color: #b779ff; --vvd-calendar-event-event-row: 13 / span 10; --vvd-calendar-event-overlap-count: 1"></vwc-calendar-event>
<vwc-calendar-event day="4" style="--vvd-calendar-event-event-color: #d6219c; --vvd-calendar-event-event-row: 13 / span 32"></vwc-calendar-event>
<vwc-calendar-event day="6" style="--vvd-calendar-event-event-color: #b779ff; --vvd-calendar-event-event-row: 15 / span 8" label="my event"></vwc-calendar-event>
<vwc-calendar-event day="1" start="23" duration="9" heading="Summer time" description="All Day"></vwc-calendar-event>
<vwc-calendar-event day="1" start="0" duration="12" color="rgb(43, 158, 250)" heading="Summer time" description="All Day"></vwc-calendar-event>
<vwc-calendar-event day="3" start="4" duration="17" color="rgb(214, 33, 156)" heading="Summer time" description="All Day"></vwc-calendar-event>
<vwc-calendar-event day="7" start="12" duration="24" color="rgb(183, 126, 249)" heading="Summer time" description="All Day"></vwc-calendar-event>
<vwc-calendar-event day="7" start="69" duration="27" color="rgb(50, 175, 76)" heading="Summer time" description="All Day"></vwc-calendar-event>
<vwc-calendar-event day="4" start="24" duration="12" color="rgb(50, 175, 76)" heading="Summer time" description="All Day" overlap-count="2"></vwc-calendar-event>
<vwc-calendar-event day="4" start="26" duration="27" color="rgb(43, 158, 250)" heading="Summer time" description="All Day"></vwc-calendar-event>
</vwc-calendar>`;

export const Basic = Template.bind({});
Expand Down
15 changes: 15 additions & 0 deletions components/calendar/test/calendar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ describe('calendar', () => {
expect(actualElement.shadowRoot.innerHTML).to.equalSnapshot();
});

it('should set cells in correct day column', async () => {
const [actualElement] = addElement(
textToDomToParent(`<${COMPONENT_NAME}>Button Text</${COMPONENT_NAME}>`)
);
await waitNextTask();

const { shadowRoot } = actualElement;
const cells = shadowRoot.querySelectorAll('.calendar > [role="listitem"i]');

const isCorrectColumns = Array.from(cells).every((cell, i) => getComputedStyle(cell)
.getPropertyValue('--column') == ~~(i / 24) + 1);

expect(isCorrectColumns).to.equal(true);
});

describe('API', () => {
it('should reflect weekdays as set by property', async () => {
const [actualElement] = addElement(
Expand Down

0 comments on commit 1f77e91

Please sign in to comment.