Mostly done

This commit is contained in:
Schmelczer András 2019-12-29 15:30:41 +01:00
parent 632a7703ff
commit 10015a4ebe
23 changed files with 258 additions and 158 deletions

View file

@ -1,11 +1,20 @@
<component name="ProjectDictionaryState"> <component name="ProjectDictionaryState">
<dictionary name="Schme"> <dictionary name="Schme">
<words> <words>
<w>contenthash</w>
<w>ffffff</w> <w>ffffff</w>
<w>gifsicle</w>
<w>imagemin</w>
<w>jpegtran</w>
<w>lato</w> <w>lato</w>
<w>mozjpeg</w>
<w>noquotes</w>
<w>opacify</w> <w>opacify</w>
<w>optipng</w>
<w>pngquant</w>
<w>raleway</w> <w>raleway</w>
<w>transparentize</w> <w>transparentize</w>
<w>webp</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

31
.idea/workspace.xml generated
View file

@ -2,40 +2,29 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="8edc47ab-1265-4111-9771-536b24cc9310" name="Default Changelist" comment=""> <list default="true" id="8edc47ab-1265-4111-9771-536b24cc9310" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/src/page/background/blob.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/framework/helper.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/framework/helper.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/about/about.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/about/about.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/about/about.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/background.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/background.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/background/background.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/background.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/background/background.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/background/blob.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/blob.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/content/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/footer/footer.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/footer/footer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans/open-sans-v17-latin_latin-ext-regular.eot" beforeDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans/open-sans-v17-latin_latin-ext-regular.svg" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans/open-sans-v17-latin_latin-ext-regular.ttf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans/open-sans-v17-latin_latin-ext-regular.woff" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans/open-sans-v17-latin_latin-ext-regular.woff2" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans_italic/open-sans-v17-latin-ext_latin-italic.eot" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans_italic/open-sans-v17-latin-ext_latin-italic.svg" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans_italic/open-sans-v17-latin-ext_latin-italic.ttf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans_italic/open-sans-v17-latin-ext_latin-italic.woff" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/open_sans_italic/open-sans-v17-latin-ext_latin-italic.woff2" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/raleway/raleway-v14-latin_latin-ext-regular.eot" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/raleway/raleway-v14-latin_latin-ext-regular.svg" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/raleway/raleway-v14-latin_latin-ext-regular.ttf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/raleway/raleway-v14-latin_latin-ext-regular.woff" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/static/fonts/raleway/raleway-v14-latin_latin-ext-regular.woff2" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/a.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/a.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/style/a.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/a.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/fonts.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/fonts.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/style/fonts.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/fonts.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/mixins.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/mixins.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/style/mixins.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/mixins.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/vars.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/vars.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/style/vars.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/vars.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/styles.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/styles.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/styles.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/styles.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/webpack.config.js" beforeDir="false" afterPath="$PROJECT_DIR$/webpack.config.js" afterDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@ -131,7 +120,7 @@
<workItem from="1577348003642" duration="4876000" /> <workItem from="1577348003642" duration="4876000" />
<workItem from="1577451432189" duration="11000" /> <workItem from="1577451432189" duration="11000" />
<workItem from="1577469180612" duration="18000" /> <workItem from="1577469180612" duration="18000" />
<workItem from="1577526744211" duration="24077000" /> <workItem from="1577526744211" duration="38046000" />
</task> </task>
<servers /> <servers />
</component> </component>

View file

@ -12,8 +12,13 @@
"type": "git", "type": "git",
"url": "git+https://github.com/schmelczerandras/timeline.git" "url": "git+https://github.com/schmelczerandras/timeline.git"
}, },
"keywords": [], "keywords": [
"author": "", "CV",
"portfolio",
"resume",
"resumé"
],
"author": "András Schmelczer",
"license": "ISC", "license": "ISC",
"bugs": { "bugs": {
"url": "https://github.com/schmelczerandras/timeline/issues" "url": "https://github.com/schmelczerandras/timeline/issues"
@ -24,12 +29,16 @@
"css-loader": "^3.4.0", "css-loader": "^3.4.0",
"file-loader": "^5.0.2", "file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"image-webpack-loader": "^6.0.0",
"mini-css-extract-plugin": "^0.9.0", "mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.0", "node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"resolve-url-loader": "^3.1.1", "resolve-url-loader": "^3.1.1",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"style-loader": "^1.0.2", "style-loader": "^1.0.2",
"svg-url-loader": "^3.0.3",
"terser-webpack-plugin": "^2.3.1",
"ts-loader": "^6.2.1", "ts-loader": "^6.2.1",
"typescript": "^3.7.3", "typescript": "^3.7.3",
"webpack": "^4.41.4", "webpack": "^4.41.4",

View file

@ -10,12 +10,17 @@
<meta property="og:url" content="https://schmelczer.dev"> <meta property="og:url" content="https://schmelczer.dev">
<meta property="og:image" content="https://schmelczer.dev/og-image.jpg"> <meta property="og:image" content="https://schmelczer.dev/og-image.jpg">
<meta name="description" content="You can view my projects on a timeline.">
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="theme-color" content="#aa4465" /> <meta name="theme-color" content="#AA4465" />
<title>Portfolio</title> <title>Portfolio - András Schmelczer</title>
</head> </head>
<body> <body>
<main></main> <main>
<noscript>
<h1>Javascript is required for this website.</h1>
</noscript>
</main>
</body> </body>
</html> </html>

View file

@ -4,15 +4,7 @@
#about { #about {
@include important-card(); @include important-card();
$img-size: 190px; $img-size: 125px;
position: relative;
width: $body-width;
margin-top: calc(#{$normal-margin} + #{$img-size} * 1 / 3);
h1 {
text-align: left;
}
h1, h1,
img, img,
@ -21,29 +13,49 @@
@include title-font(); @include title-font();
} }
.placeholder {
@include square(calc(#{$img-size} * 2 / 3 - #{$normal-margin}));
box-sizing: content-box;
float: left;
margin: 0 0.75ex 0.75ex 0;
}
img { img {
@include square($img-size); @include square($img-size);
position: absolute;
left: 0;
top: 0;
transform: translateY(-$img-size * 1/3) translateX(-$img-size * 1/3);
border-radius: 100%; border-radius: 100%;
cursor: pointer; cursor: pointer;
} }
@media (max-width: $breakpoint-width) {
}
p { p {
@include main-font(); @include main-font();
text-align: justify; text-align: justify;
margin-top: $small-margin; margin-top: $small-margin;
} }
@media (max-width: $breakpoint-width) {
h1 {
margin-top: $small-margin;
}
}
@media (min-width: $breakpoint-width) {
$img-size: 190px;
width: $body-width;
margin: calc(#{$normal-margin} + #{$img-size} * 1 / 3) auto 0 auto;
position: relative;
border-radius: $border-radius;
img {
@include square($img-size);
position: absolute;
left: 0;
top: 0;
transform: translateY(-$img-size * 1/3) translateX(-$img-size * 1/3);
}
.placeholder {
@include square(calc(#{$img-size} * 2 / 3 - #{$normal-margin}));
box-sizing: content-box;
float: left;
margin: 0 0.75ex 0.75ex 0;
}
h1 {
text-align: left;
}
}
} }

View file

@ -9,16 +9,16 @@
transform-style: preserve-3d; transform-style: preserve-3d;
overflow: hidden; overflow: hidden;
transition: height $slow-transition-time, width $slow-transition-time; transition: height $long-transition-time, width $long-transition-time;
div { div {
border-radius: 10000px; border-radius: 10000px;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 160px; width: 130px;
transition: transform $slow-transition-time, opacity $slow-transition-time; transition: transform $long-transition-time, opacity $long-transition-time;
animation: fade-in 1s linear; animation: fade-in 1s linear;
@keyframes fade-in { @keyframes fade-in {

View file

@ -11,12 +11,12 @@ import { generate } from "./background.html";
export class PageBackground extends PageElement { export class PageBackground extends PageElement {
private blobs: Array<Blob> = []; private blobs: Array<Blob> = [];
private blobSpacing = 300; private blobSpacing = 350;
public constructor(private start: PageElement, private end: PageElement) { public constructor(private start: PageElement, private end: PageElement) {
super(); super();
this.setElement(createElement(generate())); this.setElement(createElement(generate()));
Blob.initialize(20, 40, 5); Blob.initialize(10, 30, 5);
} }
protected handleEvent(event: PageEvent, parent: PageElement) { protected handleEvent(event: PageEvent, parent: PageElement) {
@ -24,7 +24,7 @@ export class PageBackground extends PageElement {
this.bindListeners(parent); this.bindListeners(parent);
this.resize(parent); this.resize(parent);
} else if (event.type === PageEventType.onBodyDimensionsChanged) { } else if (event.type === PageEventType.onBodyDimensionsChanged) {
this.resize(parent, event.data.deltaHeight); this.resize(parent, event.data?.deltaHeight);
} }
} }
@ -44,10 +44,9 @@ export class PageBackground extends PageElement {
this.getElement().style.width = `${width}px`; this.getElement().style.width = `${width}px`;
this.getElement().style.height = `${height}px`; this.getElement().style.height = `${height}px`;
const requiredBlobCount = const requiredBlobCount = Math.round(
width > 900 ? Math.round((width * height) / this.blobSpacing ** 2) : 0; (width * height) / this.blobSpacing ** 2
);
console.log(requiredBlobCount);
while (requiredBlobCount > this.blobs.length) { while (requiredBlobCount > this.blobs.length) {
const blob = new Blob(); const blob = new Blob();
@ -55,7 +54,7 @@ export class PageBackground extends PageElement {
this.blobs.push(blob); this.blobs.push(blob);
} }
const random = randomFactory(2322); const random = randomFactory(2662);
this.blobs.forEach((b, i) => { this.blobs.forEach((b, i) => {
if (i >= requiredBlobCount) { if (i >= requiredBlobCount) {

View file

@ -7,7 +7,7 @@ import {
} from "../../framework/helper"; } from "../../framework/helper";
export class Blob { export class Blob {
private static readonly creatorRandom = randomFactory(42); private static readonly creatorRandom = randomFactory(44);
private static readonly colors = ["#fff9e0", "#ffd6d6"]; private static readonly colors = ["#fff9e0", "#ffd6d6"];
private static zMin: number; private static zMin: number;
private static zMax: number; private static zMax: number;

View file

@ -18,7 +18,7 @@ export class PageContent extends PageElement {
.map(element => { .map(element => {
if (PageContent.isTyped(element)) { if (PageContent.isTyped(element)) {
if (element.type === "a") { if (element.type === "a") {
return `<a href="${element.href}" target="_blank"> ${element.text} </a>`; return `<a href="${element.href}" rel="noreferrer" target="_blank"> ${element.text} </a>`;
} }
if (element.type === "video") { if (element.type === "video") {
return `<video controls><source src="${element.src}" /></video>`; return `<video controls><source src="${element.src}" /></video>`;

View file

@ -19,11 +19,11 @@ export const generate = ({
<h2>${title}</h2> <h2>${title}</h2>
<ul> <ul>
<li> <li>
<img src="${cvIcon}" alt="CV" /> <img src="${cvIcon}" alt="CV" class="no-open" />
<a id="cv" target="_blank">${cvName}</a> <a id="cv" href="${cv}" target="_blank">${cvName}</a>
</li> </li>
<li> <li>
<img src="${emailIcon}" alt="email" /> <img src="${emailIcon}" alt="email" class="no-open"/>
<a id="email" href="mailto:${email}">${email}</a> <a id="email" href="mailto:${email}">${email}</a>
</li> </li>
</ul> </ul>

View file

@ -4,10 +4,8 @@
footer#page-footer { footer#page-footer {
text-align: center; text-align: center;
margin: $normal-margin auto 0 auto; margin: $large-margin auto 0 auto;
padding: $normal-margin $normal-margin $line-height $normal-margin;
width: 100%; width: 100%;
// backdrop-filter: blur($blur-radius);
h2 { h2 {
@include title-font(); @include title-font();
@ -16,7 +14,7 @@ footer#page-footer {
ul { ul {
list-style: none; list-style: none;
display: inline-block; display: inline-block;
margin-top: calc(#{$small-margin} / 2 + #{$normal-margin} / 2); margin-top: $normal-margin;
text-align: left; text-align: left;
li { li {
@ -40,7 +38,7 @@ footer#page-footer {
aside.other { aside.other {
@include center-children(); @include center-children();
margin: calc(2 * #{$normal-margin}) auto 0 auto; margin: $large-margin auto $line-height auto;
width: $body-width; width: $body-width;
h6 { h6 {

View file

@ -24,7 +24,9 @@ export class PageImageViewer extends PageElement {
); );
images images
.filter( .filter(
(img: HTMLImageElement) => img.parentElement !== this.getElement() (img: HTMLImageElement) =>
img.parentElement !== this.getElement() &&
!img.classList.contains("no-open")
) )
.forEach( .forEach(
(img: HTMLImageElement) => (img.onclick = this.handleClick.bind(this)) (img: HTMLImageElement) => (img.onclick = this.handleClick.bind(this))

View file

@ -7,7 +7,6 @@ import { PageImageViewer } from "./image-viewer/image-viewer";
import { Page } from "../framework/page"; import { Page } from "../framework/page";
export const create = ({ config, header, timeline, footer }: Portfolio) => { export const create = ({ config, header, timeline, footer }: Portfolio) => {
document.title = header.name;
const pageHeader = new PageHeader(header, config.aPictureOf); const pageHeader = new PageHeader(header, config.aPictureOf);
const pageFooter = new PageFooter(footer); const pageFooter = new PageFooter(footer);

View file

@ -9,11 +9,10 @@ export const generate = (
): html => ` ): html => `
<section class="timeline-element"> <section class="timeline-element">
<div class="line"> <div class="line">
<p class="date-wide-screen">${date}</p> <p class="date">${date}</p>
</div> </div>
<div class="card"> <div class="card">
<h2>${title}</h2> <h2>${title}</h2>
<p class="date-narrow-screen">${date}</p>
<div class="image-container"> <div class="image-container">
<img src="${picture}" alt="${picture}"/> <img src="${picture}" alt="${picture}"/>
</div> </div>
@ -21,10 +20,10 @@ export const generate = (
${ ${
more more
? ` ? `
<div id="more"></div> <div class="more"></div>
<div class="buttons"> <div class="buttons">
<a id="show-more">${showMore}</a> <a class="show-more">${showMore}</a>
<a id="show-less">${showLess}</a> <a class="show-less">${showLess}</a>
</div> </div>
` `
: "" : ""

View file

@ -4,46 +4,63 @@
.timeline-element { .timeline-element {
display: flex; display: flex;
.date-narrow-screen,
.date-wide-screen {
@include insignificant-font();
}
.date-wide-screen {
color: $accent-color;
}
.line { .line {
@media (max-width: $breakpoint-width) {
display: none;
}
position: relative; position: relative;
margin: 0 $small-margin 0 $icon-size / 2;
border-left: $line-width solid $accent-color; border-left: $line-width solid $accent-color;
&:before { &:before {
content: ""; content: "";
@include square($icon-size); @include square($icon-size);
position: absolute; position: absolute;
top: 33%;
left: calc(-0.5 * #{$icon-size} - (1.5 * #{$line-width})); left: calc(-0.5 * #{$icon-size} - (1.5 * #{$line-width}));
border: $line-width solid $accent-color; border: $line-width solid $accent-color;
border-radius: 100%; border-radius: 100%;
background: $background; background: $background;
} }
.date-wide-screen { .date {
position: relative; @include insignificant-font();
top: calc(33% + #{$icon-size} + 2ch);
transform: rotate(30deg);
margin: 0 $normal-margin 0 calc(#{$line-width} + 1ex);
width: 100px;
} }
} }
&:not(:first-of-type) .card { @media (min-width: $breakpoint-width) {
margin-top: $normal-margin; &:not(:first-of-type) .card {
margin-top: $large-margin;
}
.line {
&:before {
top: calc(33% - #{$icon-size} / 2);
}
.date {
position: relative;
top: calc(33% + #{$icon-size} / 2 + 1ch);
transform: rotate(30deg);
margin: 0 $normal-margin 0 calc(#{$line-width} + 1ex);
width: 100px;
}
}
}
@media (max-width: $breakpoint-width) {
flex-direction: column;
align-items: center;
&:before {
top: calc(50% - #{$icon-size} / 2);
}
.line {
@include center-children();
height: 150px;
width: 50%;
.date {
margin-left: calc(#{$icon-size} / 2 + #{$small-margin});
width: 200px;
}
}
} }
.card { .card {
@ -58,18 +75,9 @@
@include sub-title-font(); @include sub-title-font();
} }
.date-narrow-screen {
@media (min-width: $breakpoint-width) {
display: none;
}
margin: $small-margin 0 0 0;
color: $light-text-color;
}
.image-container { .image-container {
font-size: 0; font-size: 0;
box-shadow: inset $shadow; box-shadow: inset $shadow1, inset $shadow2;
pointer-events: none; pointer-events: none;
img { img {
pointer-events: all; pointer-events: all;
@ -83,11 +91,11 @@
font-style: italic; font-style: italic;
} }
#more { .more {
overflow: hidden; overflow: hidden;
height: 0; height: 0;
margin-top: 0; margin-top: 0;
transition: height $slow-transition-time; transition: height $long-transition-time;
} }
.buttons { .buttons {
@ -95,14 +103,14 @@
margin-top: $small-margin; margin-top: $small-margin;
* { * {
transition: opacity $slow-transition-time; transition: opacity $long-transition-time;
} }
#show-more { .show-more {
opacity: 1; opacity: 1;
} }
#show-less { .show-less {
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
position: absolute; position: absolute;

View file

@ -20,7 +20,7 @@ export class PageTimelineElement extends PageElement {
const content = new PageContent(timelineElement.more); const content = new PageContent(timelineElement.more);
super([content]); super([content]);
this.isOpen = false; this.isOpen = false;
this.more = root.querySelector("#more"); this.more = root.querySelector(".more");
this.more.appendChild(content.getElement()); this.more.appendChild(content.getElement());
window.addEventListener("resize", this.handleResize.bind(this)); window.addEventListener("resize", this.handleResize.bind(this));
root root
@ -31,8 +31,8 @@ export class PageTimelineElement extends PageElement {
} }
private toggleOpen() { private toggleOpen() {
const showMore = this.query("#show-more") as HTMLElement; const showMore = this.query(".show-more") as HTMLElement;
const showLess = this.query("#show-less") as HTMLElement; const showLess = this.query(".show-less") as HTMLElement;
if (this.isOpen) { if (this.isOpen) {
PageTimelineElement.show(showMore); PageTimelineElement.show(showMore);
PageTimelineElement.hide(showLess); PageTimelineElement.hide(showLess);
@ -51,6 +51,14 @@ export class PageTimelineElement extends PageElement {
type: PageEventType.onBodyDimensionsChanged, type: PageEventType.onBodyDimensionsChanged,
data: { deltaHeight } data: { deltaHeight }
}); });
setTimeout(
() =>
this.eventBroadcaster?.broadcastEvent({
type: PageEventType.onBodyDimensionsChanged
}),
350
);
} }
private static hide(element: HTMLElement) { private static hide(element: HTMLElement) {

View file

@ -1,5 +1,10 @@
@import "../../style/vars"; @import "../../style/vars";
main#timeline { #timeline {
margin-top: $normal-margin; width: $body-width;
margin: $large-margin auto 0 auto;
@media (max-width: $breakpoint-width) {
margin: auto;
}
} }

View file

@ -12,7 +12,7 @@ a {
$border-shift: 10px; $border-shift: 10px;
transition: transform $slow-transition-time; transition: transform $long-transition-time;
$dot-size: 4px; $dot-size: 4px;
&:before { &:before {
@ -38,7 +38,7 @@ a {
width: calc(100% + #{$border-shift}); width: calc(100% + #{$border-shift});
z-index: 0; z-index: 0;
border-bottom: $dot-size dotted $accent-color; border-bottom: $dot-size dotted $accent-color;
transition: transform $slow-transition-time; transition: transform $long-transition-time;
} }
&:hover { &:hover {

View file

@ -1,3 +1,5 @@
// https://google-webfonts-helper.herokuapp.com/fonts/montserrat?subsets=latin
/* lato-regular - latin */ /* lato-regular - latin */
@font-face { @font-face {
font-family: "Lato"; font-family: "Lato";

View file

@ -8,30 +8,27 @@
%card { %card {
text-align: center; text-align: center;
border-radius: $border-radius;
padding: $normal-margin; padding: $normal-margin;
box-shadow: $shadow; box-shadow: $shadow1, $shadow2;
z-index: 1; z-index: 1;
@media (max-width: $breakpoint-width) { @media (min-width: $breakpoint-width) {
& { transition: box-shadow $long-transition-time;
transition: box-shadow $fast-transition-time;
&:hover { &:hover {
box-shadow: 0 0 3px rgba(0, 0, 0, 0.05); box-shadow: $shadow3, $shadow2;
}
} }
} }
} }
@mixin card() { @mixin card() {
@extend %card; @extend %card;
border-radius: $border-radius;
background-color: $card-color; background-color: $card-color;
} }
@mixin important-card() { @mixin important-card() {
@extend %card; @extend %card;
background-color: $accent-color; background-color: $accent-color;
* { * {
@ -53,6 +50,11 @@
font: 400 3.5rem "Montserrat", serif; font: 400 3.5rem "Montserrat", serif;
font-style: normal; font-style: normal;
line-height: 1; line-height: 1;
@media (max-width: $breakpoint-width) {
font-size: 3rem;
line-height: 1.1;
}
} }
@mixin sub-title-font() { @mixin sub-title-font() {

View file

@ -1,8 +1,6 @@
@import "fonts"; @import "fonts";
$background-start: white;
$background-end: white;
$background: white; $background: white;
$background-gradient: linear-gradient(90deg, #fff9e0 0, #ffd6d6 100%);
$normal-text-color: #31343f; $normal-text-color: #31343f;
$light-text-color: #7a7d8e; $light-text-color: #7a7d8e;
@ -12,32 +10,40 @@ $card-color: #ffffff;
$accent-color: #aa4465; $accent-color: #aa4465;
$scrollbar-color: #ffd6d6; $scrollbar-color: #ffd6d6;
$fast-transition-time: 220ms; $short-transition-time: 220ms;
$slow-transition-time: 350ms; $long-transition-time: 350ms;
$line-width: 3px; $line-width: 3px;
$border-radius: 25px; $border-radius: 15px;
$breakpoint-width: 900px; $breakpoint-width: 925px;
$large-margin: var(--large-margin);
$normal-margin: var(--normal-margin); $normal-margin: var(--normal-margin);
$small-margin: var(--small-margin); $small-margin: var(--small-margin);
$line-height: 18px; $line-height: 18px;
$shadow: 0 0 5px rgba(0, 0, 0, 0.125); $shadow1: var(--shadow1);
$shadow2: var(--shadow2);
$shadow3: 0 0 15px 4px rgba(0, 0, 0, 0.1);
$blur-radius: 9px;
$icon-size: var(--icon-size); $icon-size: var(--icon-size);
$body-width: var(--body-width); $body-width: var(--body-width);
:root { :root {
--large-margin: 70px;
--normal-margin: 45px; --normal-margin: 45px;
--small-margin: 25px; --small-margin: 25px;
--icon-size: 35px; --icon-size: 35px;
--body-width: 765px; --body-width: 765px;
--shadow1: 0 0 10px 2px rgba(0, 0, 0, 0.075);
--shadow2: 0 0 1px rgba(0, 0, 0, 0.2);
@media (max-width: $breakpoint-width) { @media (max-width: $breakpoint-width) {
--normal-margin: 35px; --large-margin: 60px;
--normal-margin: 30px;
--small-margin: 15px; --small-margin: 15px;
--icon-size: 20px; --icon-size: 25px;
--body-width: 85%; --body-width: 90%;
--shadow1: 0 0 10px 2px rgba(0, 0, 0, 0.05);
--shadow2: 0 0 1px rgba(0, 0, 0, 0.125);
} }
} }

View file

@ -20,17 +20,20 @@
} }
html { html {
background-color: white; background-color: $background;
height: 100%; height: 100%;
} }
body { body {
@include main-font(); @include main-font();
margin: auto;
height: 100%; height: 100%;
width: 100%;
& > main { & > main {
noscript {
@include square(100%);
@include center-children();
}
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
@ -48,11 +51,6 @@ body {
border-radius: $border-radius; border-radius: $border-radius;
} }
} }
& > * {
width: $body-width;
margin: auto;
}
} }
} }
@ -62,3 +60,9 @@ video {
height: auto; height: auto;
object-fit: contain; object-fit: contain;
} }
@media (max-width: $breakpoint-width) {
html {
font-size: 0.8em;
}
}

View file

@ -1,8 +1,12 @@
const path = require("path"); const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isProduction = process.env.NODE_ENV === "production";
module.exports = { module.exports = {
watchOptions: { watchOptions: {
ignored: /node_modules/ ignored: /node_modules/
@ -10,6 +14,9 @@ module.exports = {
devServer: { devServer: {
host: "0.0.0.0" host: "0.0.0.0"
}, },
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]
},
plugins: [ plugins: [
new CleanWebpackPlugin(), new CleanWebpackPlugin(),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
@ -17,7 +24,10 @@ module.exports = {
xhtml: true, xhtml: true,
template: "./src/index.html" template: "./src/index.html"
}), }),
new MiniCssExtractPlugin() new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css"
})
], ],
entry: { entry: {
index: "./src/index.ts" index: "./src/index.ts"
@ -25,12 +35,46 @@ module.exports = {
module: { module: {
rules: [ rules: [
{ {
test: /\.(png|svg|jpe?g|gif|mp4)$/i, test: /\.(png|jpe?g|gif|mp4)$/i,
use: { use: [
loader: "file-loader", {
query: { loader: "file-loader",
outputPath: "static/" query: {
outputPath: "static/"
}
},
{
loader: "image-webpack-loader",
options: {
disable: !isProduction,
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: true
},
pngquant: {
quality: [0.65, 0.9],
speed: 4
},
gifsicle: {
interlaced: false
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
} }
]
},
{
test: /\.svg$/,
loader: "svg-url-loader",
options: {
limit: 10 * 1024,
noquotes: true
} }
}, },
{ {
@ -98,7 +142,7 @@ module.exports = {
extensions: [".ts", ".js"] extensions: [".ts", ".js"]
}, },
output: { output: {
filename: "[name].bundle.js", filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist") path: path.resolve(__dirname, "dist")
} }
}; };