Convert to component based architecture
This commit is contained in:
parent
eb2075aec5
commit
cdaa423b8a
70 changed files with 1942 additions and 484 deletions
80
src/page/timeline/timeline-element/timeline-element.scss
Normal file
80
src/page/timeline/timeline-element/timeline-element.scss
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
@import "../../../style/mixins";
|
||||
@import "../../../style/vars";
|
||||
|
||||
.timeline-element {
|
||||
display: flex;
|
||||
|
||||
.date-narrow-screen,
|
||||
.date-wide-screen {
|
||||
font: $text-font;
|
||||
}
|
||||
|
||||
.line {
|
||||
@media (max-width: $breakpoint-width) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
margin: 0 $small-margin 0 $icon-size / 2;
|
||||
border-left: $line-width solid $normal-text-color;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
@include square($icon-size);
|
||||
position: absolute;
|
||||
top: 33%;
|
||||
left: -0.5 * $icon-size - (1.5 * $line-width);
|
||||
border: $line-width solid $normal-text-color;
|
||||
border-radius: 100%;
|
||||
background: $background;
|
||||
}
|
||||
|
||||
.date-wide-screen {
|
||||
position: relative;
|
||||
top: calc(33% + #{$icon-size} + 1ch);
|
||||
margin: 0 $normal-margin 0 calc(#{$line-width} + 1ex);
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-of-type) .card {
|
||||
margin-top: $normal-margin;
|
||||
}
|
||||
|
||||
.card {
|
||||
@include card();
|
||||
|
||||
h2 {
|
||||
font: $sub-title-font;
|
||||
}
|
||||
|
||||
.date-narrow-screen {
|
||||
@media (min-width: $breakpoint-width) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
margin: $small-margin 0 0 0;
|
||||
color: $light-text-color;
|
||||
}
|
||||
|
||||
#more {
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
transition: height $transition-time;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
position: relative;
|
||||
* {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
transition: opacity $transition-time;
|
||||
}
|
||||
|
||||
#show-less {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/page/timeline/timeline-element/timeline-element.ts
Normal file
91
src/page/timeline/timeline-element/timeline-element.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import { TimelineElement } from "../../../model/portfolio";
|
||||
import { PageContent } from "../../content/content";
|
||||
import "./timeline-element.scss";
|
||||
import { PageElement } from "../../../framework/page-element";
|
||||
import { createElement } from "../../../framework/element-factory";
|
||||
|
||||
export class PageTimelineElement extends PageElement {
|
||||
private isOpen;
|
||||
private more: HTMLElement;
|
||||
|
||||
public constructor(
|
||||
{ date, title, picture, description, more, link }: TimelineElement,
|
||||
showMore: string,
|
||||
showLess: string
|
||||
) {
|
||||
const root = createElement(`
|
||||
<section class="timeline-element">
|
||||
<div class="line">
|
||||
<p class="date-wide-screen">${date}</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>${title}</h2>
|
||||
<p class="date-narrow-screen">${date}</p>
|
||||
<img src="${picture}" alt="${picture}"/>
|
||||
<p class="description">${description}</p>
|
||||
${
|
||||
more
|
||||
? `
|
||||
<div id="more"></div>
|
||||
<div class="buttons">
|
||||
<a id="show-more">${showMore}</a>
|
||||
<a id="show-less">${showLess}</a>
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
${
|
||||
link
|
||||
? `
|
||||
<a href="${link}" target="_blank">${link}</a>`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
`);
|
||||
|
||||
if (more) {
|
||||
const content = new PageContent(more);
|
||||
super([content]);
|
||||
this.isOpen = false;
|
||||
this.more = root.querySelector("#more");
|
||||
this.more.appendChild(content.getElement());
|
||||
window.addEventListener("resize", this.handleResize.bind(this));
|
||||
root
|
||||
.querySelector(".buttons")
|
||||
.addEventListener("click", this.toggleOpen.bind(this));
|
||||
} else super();
|
||||
this.setElement(root);
|
||||
}
|
||||
|
||||
private toggleOpen() {
|
||||
const showMore = this.getElement().querySelector(
|
||||
"#show-more"
|
||||
) as HTMLElement;
|
||||
const showLess = this.getElement().querySelector(
|
||||
"#show-less"
|
||||
) as HTMLElement;
|
||||
if (this.isOpen) {
|
||||
this.more.style.height = "0";
|
||||
showMore.style.opacity = "1";
|
||||
showLess.style.opacity = "0";
|
||||
} else {
|
||||
this.openMoreToFullHeight();
|
||||
showMore.style.opacity = "0";
|
||||
showLess.style.opacity = "1";
|
||||
}
|
||||
|
||||
this.isOpen = !this.isOpen;
|
||||
}
|
||||
|
||||
private openMoreToFullHeight() {
|
||||
this.more.style.height = `${this.more.scrollHeight.toString()}px`;
|
||||
}
|
||||
|
||||
private handleResize() {
|
||||
if (this.isOpen) {
|
||||
this.more.style.height = "auto";
|
||||
setTimeout(this.openMoreToFullHeight.bind(this), 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/page/timeline/timeline.scss
Normal file
5
src/page/timeline/timeline.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@import "../../style/vars";
|
||||
|
||||
#timeline {
|
||||
margin-top: $normal-margin;
|
||||
}
|
||||
21
src/page/timeline/timeline.ts
Normal file
21
src/page/timeline/timeline.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { TimelineElement } from "../../model/portfolio";
|
||||
import "./timeline.scss";
|
||||
import { PageElement } from "../../framework/page-element";
|
||||
import { createElement } from "../../framework/element-factory";
|
||||
import { PageTimelineElement } from "./timeline-element/timeline-element";
|
||||
|
||||
export class PageTimeline extends PageElement {
|
||||
public constructor(
|
||||
timeline: Array<TimelineElement>,
|
||||
showMore: string,
|
||||
showLess: string
|
||||
) {
|
||||
const root = createElement(`<main id="timeline"></main>`);
|
||||
const elements = timeline.map(
|
||||
e => new PageTimelineElement(e, showMore, showLess)
|
||||
);
|
||||
root.append(...elements.map(e => e.getElement()));
|
||||
super(elements);
|
||||
this.setElement(root);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue