diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 61ebb65..d0d62e1 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,21 +2,31 @@ + + + - - - + + - - + + + + + + + + + + - + + + + + + + + - - - - - - @@ -104,7 +115,8 @@ - + + diff --git a/custom.d.ts b/custom.d.ts index f527fb3..762d252 100644 --- a/custom.d.ts +++ b/custom.d.ts @@ -27,3 +27,8 @@ declare module "*.mp4" { const content: string; export default content; } + +declare module "*.pdf" { + const content: string; + export default content; +} diff --git a/src/framework/page-element.ts b/src/framework/page-element.ts index a8c40a0..c49656d 100644 --- a/src/framework/page-element.ts +++ b/src/framework/page-element.ts @@ -13,16 +13,16 @@ export abstract class PageElement { this.element = value; } - protected eventGenerator: PageElement; + protected eventBroadcaster: PageElement; protected constructor(private children: Array = []) {} - public giveEvent(event: PageEvent, parent: PageElement = null) { - if (event.type === PageEventType.eventGeneratorChanged) { - this.eventGenerator = event.data; + public broadcastEvent(event: PageEvent, parent: PageElement = null) { + if (event.type === PageEventType.eventBroadcasterChanged) { + this.eventBroadcaster = event.data; } this.handleEvent(event, parent); - this.children.forEach(c => c.giveEvent(event, this)); + this.children.forEach(c => c.broadcastEvent(event, this)); } protected query(query: string): HTMLElement | null { diff --git a/src/framework/page-event.ts b/src/framework/page-event.ts index d5fceb3..0a682eb 100644 --- a/src/framework/page-event.ts +++ b/src/framework/page-event.ts @@ -6,5 +6,5 @@ export class PageEvent { export enum PageEventType { onLoad, onBodyDimensionsChanged, - eventGeneratorChanged + eventBroadcasterChanged } diff --git a/src/framework/page.ts b/src/framework/page.ts index 102e93a..02be160 100644 --- a/src/framework/page.ts +++ b/src/framework/page.ts @@ -8,11 +8,11 @@ export class Page extends PageElement { ) { super(children); this.setElement(rootElement); - this.giveEvent( - { type: PageEventType.eventGeneratorChanged, data: this }, + this.broadcastEvent( + { type: PageEventType.eventBroadcasterChanged, data: this }, this ); rootElement.append(...children.map(e => e.getElement()).filter(e => e)); - this.giveEvent({ type: PageEventType.onLoad }, this); + this.broadcastEvent({ type: PageEventType.onLoad }, this); } } diff --git a/src/model/portfolio.ts b/src/model/portfolio.ts index 65a2c5c..c10fe76 100644 --- a/src/model/portfolio.ts +++ b/src/model/portfolio.ts @@ -12,8 +12,6 @@ export interface Config { showMore: string; showLess: string; aPictureOf: string; - cvName: string; - lastEdit: Date; } export interface Header { @@ -32,6 +30,12 @@ export interface TimelineElement { } export interface Footer { + title: string; email: string; cv: url; + cvName: string; + githubLinkName: string; + githubLink: url; + lastEditName: string; + lastEdit: Date; } diff --git a/src/page/about/about.scss b/src/page/about/about.scss index 54aa586..6aed5e1 100644 --- a/src/page/about/about.scss +++ b/src/page/about/about.scss @@ -2,7 +2,8 @@ @import "../../style/vars"; #about { - margin-top: $normal-margin; + margin-top: $normal-margin - $small-margin; + padding: $small-margin; header { @include center-children(); diff --git a/src/page/background/background.scss b/src/page/background/background.scss index a48d3b0..b56468e 100644 --- a/src/page/background/background.scss +++ b/src/page/background/background.scss @@ -14,6 +14,6 @@ position: absolute; left: 0; top: 0; - width: 100px; + width: 160px; } } diff --git a/src/page/background/background.ts b/src/page/background/background.ts index 17ed789..a9b2f18 100644 --- a/src/page/background/background.ts +++ b/src/page/background/background.ts @@ -62,9 +62,9 @@ export class PageBackground extends PageElement { generate( count, () => choose(this.colors, random), - () => randomInInterval(150, 750, random), + () => randomInInterval(160, 750, random), () => { - const z = randomInInterval(-5, -15, random); + const z = randomInInterval(-12, -25, random); return ` translateX(${randomWithKnownZ(-z, width)}px) translateY(${randomWithKnownZ(-z, height)}px) diff --git a/src/page/footer/footer.html.ts b/src/page/footer/footer.html.ts index 0571d8f..9bf3a34 100644 --- a/src/page/footer/footer.html.ts +++ b/src/page/footer/footer.html.ts @@ -1,10 +1,34 @@ import { Footer } from "../../model/portfolio"; -import { html } from "../../model/misc"; -import "./footer.scss"; +import { html, url } from "../../model/misc"; -export const generate = ({ email, cv }: Footer, cvName: string): html => ` +import "./footer.scss"; +import cvIcon from "../../static/icons/cv.svg"; +import emailIcon from "../../static/icons/at.svg"; + +export const generate = ({ + title, + email, + cv, + cvName, + lastEditName, + lastEdit, + githubLinkName, + githubLink +}: Footer): html => ` `; diff --git a/src/page/footer/footer.scss b/src/page/footer/footer.scss index 7d7cce7..9e7a8f7 100644 --- a/src/page/footer/footer.scss +++ b/src/page/footer/footer.scss @@ -2,7 +2,50 @@ @import "../../style/vars"; footer#page-footer { - @include card(); - @include center-children(); - margin: $normal-margin auto; + text-align: center; + + margin: $small-margin auto 0 auto; + padding: $normal-margin $normal-margin $line-height $normal-margin; + width: 100%; + backdrop-filter: blur(5px); + + h2 { + @include title-font(); + } + + ul { + list-style: none; + display: inline-block; + margin-top: $normal-margin; + text-align: left; + + li { + @include center-children(); + justify-content: flex-start; + + &:not(:first-child) { + padding-top: $line-height; + } + + img { + @include max-square($icon-size); + margin-right: $small-margin; + } + + a { + font-size: 1.4rem; + } + } + } + + aside.other { + @include center-children(); + margin: $normal-margin auto 0 auto; + width: $body-width; + + h6 { + @include insignificant-font(); + opacity: 0.4; + } + } } diff --git a/src/page/footer/footer.ts b/src/page/footer/footer.ts index 1d2d578..789c31a 100644 --- a/src/page/footer/footer.ts +++ b/src/page/footer/footer.ts @@ -5,8 +5,8 @@ import { generate } from "./footer.html"; import { createElement } from "../../framework/helper"; export class PageFooter extends PageElement { - constructor(footer: Footer, cvName: string) { + constructor(footer: Footer) { super(); - this.setElement(createElement(generate(footer, cvName))); + this.setElement(createElement(generate(footer))); } } diff --git a/src/page/image-viewer/image-viewer.html.ts b/src/page/image-viewer/image-viewer.html.ts index 31d9030..8900362 100644 --- a/src/page/image-viewer/image-viewer.html.ts +++ b/src/page/image-viewer/image-viewer.html.ts @@ -3,7 +3,7 @@ import cancel from "../../static/icons/cancel.svg"; import "./image-viewer.scss"; export const generate = (): html => ` -
+
currently opened photo cancel
diff --git a/src/page/image-viewer/image-viewer.scss b/src/page/image-viewer/image-viewer.scss index 088bf66..003a496 100644 --- a/src/page/image-viewer/image-viewer.scss +++ b/src/page/image-viewer/image-viewer.scss @@ -1,7 +1,7 @@ @import "../../style/vars"; @import "../../style/mixins"; -.photo-viewer { +#image-viewer { @include center-children(); display: none; diff --git a/src/page/index.ts b/src/page/index.ts index 766fa05..2adbaba 100644 --- a/src/page/index.ts +++ b/src/page/index.ts @@ -14,7 +14,7 @@ export const create = ({ config, header, timeline, footer }: Portfolio) => { new PageBackground(), new PageHeader(header, config.aPictureOf), new PageTimeline(timeline, config.showMore, config.showLess), - new PageFooter(footer, config.cvName), + new PageFooter(footer), new PageImageViewer() ], document.body.querySelector("main") diff --git a/src/page/timeline/timeline-element/timeline-element.ts b/src/page/timeline/timeline-element/timeline-element.ts index 17def56..eea1056 100644 --- a/src/page/timeline/timeline-element/timeline-element.ts +++ b/src/page/timeline/timeline-element/timeline-element.ts @@ -44,7 +44,7 @@ export class PageTimelineElement extends PageElement { } this.isOpen = !this.isOpen; - this.eventGenerator?.giveEvent({ + this.eventBroadcaster?.broadcastEvent({ type: PageEventType.onBodyDimensionsChanged }); } diff --git a/src/portfolio.ts b/src/portfolio.ts index 9beec25..5b4febe 100644 --- a/src/portfolio.ts +++ b/src/portfolio.ts @@ -10,15 +10,14 @@ import color from "./static/media/color.jpg"; import platform from "./static/media/platform.png"; import photos from "./static/media/photos.jpg"; import led from "./static/media/led.jpg"; +import cv from "./static/cv/andras_schmelczer_cv_2020_01.pdf"; import ledVideo from "./static/media/led720.mp4"; export const portfolio: Portfolio = { config: { showMore: `Show details`, showLess: `Show less`, - aPictureOf: `a picture of`, - cvName: `Curriculum vitae`, - lastEdit: new Date(2019, 12, 22) + aPictureOf: `a picture of` }, header: { name: `AndrĂ¡s Schmelczer`, @@ -160,7 +159,13 @@ export const portfolio: Portfolio = { } ], footer: { - email: `andras.schmelczer@schdesign.hu`, - cv: `/static/media/andras_schmelczer_cv.pdf` + title: `Learn more`, + cv, + email: `andras@schmelczer.dev`, + cvName: `Curriculum vitae`, + githubLinkName: `view source`, + githubLink: `https://github.com/schmelczerandras/timeline`, + lastEditName: `Last modified on `, + lastEdit: new Date(2019, 11, 27) // months are 0 indexed } }; diff --git a/src/static/cv/andras_schmelczer_cv_2020_01.pdf b/src/static/cv/andras_schmelczer_cv_2020_01.pdf new file mode 100644 index 0000000..607eba1 Binary files /dev/null and b/src/static/cv/andras_schmelczer_cv_2020_01.pdf differ diff --git a/src/static/icons/at.svg b/src/static/icons/at.svg new file mode 100644 index 0000000..f4dd5d6 --- /dev/null +++ b/src/static/icons/at.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/style/a.scss b/src/style/a.scss new file mode 100644 index 0000000..683a6e0 --- /dev/null +++ b/src/style/a.scss @@ -0,0 +1,48 @@ +@import "vars"; +@import "mixins"; + +a { + @include insignificant-font(); + text-decoration: none; + position: relative; + cursor: pointer; + color: $accent-color; + display: inline-block; + overflow: hidden; + + $border-shift: 10px; + + transition: transform $slow-transition-time; + + &:before { + content: ""; + display: block; + position: absolute; + width: 100%; + height: $line-width; + bottom: 0; + z-index: 1; + background: linear-gradient( + 90deg, + $card-color 0, + transparentize($card-color, 1) 4px, + transparentize($card-color, 1) calc(100% - 4px), + $card-color 100% + ); + } + + &:after { + content: ""; + display: block; + width: calc(100% + #{$border-shift}); + z-index: 0; + border-bottom: $line-width dotted $accent-color; + transition: transform $slow-transition-time; + } + + &:hover { + &:after { + transform: translateX(-$border-shift); + } + } +} diff --git a/src/style/elements.scss b/src/style/elements.scss deleted file mode 100644 index 565fbe7..0000000 --- a/src/style/elements.scss +++ /dev/null @@ -1,18 +0,0 @@ -#photo-viewer { - width: 100%; - height: 100vh; - position: fixed; - top: 0; - left: 0; - background: var(--photo-viewer-color); - z-index: -3; - opacity: 0; - transition: opacity var(--transition-time); -} - -/* #photo */ -#photo-viewer > img { - max-width: 80vw; - max-height: 80vh; -} -/**/ diff --git a/src/style/mixins.scss b/src/style/mixins.scss index 8fb3373..40857ee 100644 --- a/src/style/mixins.scss +++ b/src/style/mixins.scss @@ -29,6 +29,11 @@ height: $size; } +@mixin max-square($size) { + max-width: $size; + max-height: $size; +} + @mixin title-font() { font: 400 3.33rem "Raleway", serif; } diff --git a/src/style/page.scss b/src/style/page.scss deleted file mode 100644 index dda01b1..0000000 --- a/src/style/page.scss +++ /dev/null @@ -1,84 +0,0 @@ -header, -footer, -#timeline, -#about > p:first-of-type, -#timeline > section:not(:first-of-type) > .card { - margin-top: var(--margin); -} - -#about > p { -} - -#timeline > section { - display: flex; -} - -.card { - flex: 1; -} - -#about > p, -.card > *:not(:first-child):not(:last-child), -.collapsed > *:not(:first-child) { - margin-top: var(--line-height); -} - -img { - user-select: none; - border-radius: var(--border-radius); - cursor: pointer; -} - -.description { - font-style: italic; - margin-bottom: var(--smaller-margin); -} - -.collapsed > p { - text-align: left; -} - -.collapsed { - height: 0; - overflow: hidden; - transition: height var(--transition-time); -} -.collapsed > *:last-child { - margin-bottom: var(--smaller-margin); -} - -footer { - margin-bottom: var(--margin); -} - -@media (max-width: 900px) { - body { - font-size: 0.85em; - } - - #photo { - max-width: 94vw; - } - - .card { - font-size: 0.9em; - } - - header { - flex-direction: column; - } - - h1, - #header-pic { - font-size: 3em; - } - - #header-pic { - height: 5.5ch; - margin: 0.75ex 0 0.5ex 0; - } - - #about > p { - text-align: left; - } -} diff --git a/src/styles.scss b/src/styles.scss index 831231f..2d6b622 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,8 +1,10 @@ @import "style/vars"; @import "style/mixins"; +@import "style/a"; * { margin: 0; + padding: 0; box-sizing: border-box; color: $normal-text-color; hyphens: auto; @@ -32,23 +34,23 @@ body { height: 100%; overflow-y: auto; overflow-x: hidden; - perspective: 5px; + + &::-webkit-scrollbar-track, + &::-webkit-scrollbar { + background-color: transparent; + width: 12px; + } + &::-webkit-scrollbar-thumb { + background-color: $accent-color; + border-radius: $border-radius; + } + & > * { width: $body-width; margin: auto; } } - - &::-webkit-scrollbar-track, - &::-webkit-scrollbar { - background-color: transparent; - width: 12px; - } - &::-webkit-scrollbar-thumb { - background-color: $accent-color; - border-radius: $border-radius; - } } img, @@ -58,50 +60,3 @@ video { object-fit: contain; border-radius: $border-radius; } - -a { - @include insignificant-font(); - text-decoration: none; - position: relative; - cursor: pointer; - color: $accent-color; - display: inline-block; - overflow: hidden; - - $border-shift: 10px; - - transition: transform $slow-transition-time; - - &:before { - content: ""; - display: block; - position: absolute; - width: 100%; - height: $line-width; - bottom: 0; - z-index: 1; - background: linear-gradient( - 90deg, - $card-color 0, - transparentize($card-color, 1) 4px, - transparentize($card-color, 1) calc(100% - 4px), - $card-color 100% - ); - } - - &:after { - content: ""; - display: block; - width: calc(100% + #{$border-shift}); - height: 100%; - z-index: 0; - border-bottom: $line-width dotted $accent-color; - transition: transform $slow-transition-time; - } - - &:hover { - &:after { - transform: translateX(-$border-shift); - } - } -} diff --git a/webpack.config.js b/webpack.config.js index d44585a..1c3b3ae 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -28,6 +28,16 @@ module.exports = { } } }, + { + test: /\.(pdf)$/i, + use: { + loader: "file-loader", + query: { + outputPath: "static/", + name: "[name].[ext]" + } + } + }, { test: /\.ico$/i, use: {