diff --git a/src/data/portfolio.ts b/src/data/portfolio.ts index 87a2b2d..ad2197a 100644 --- a/src/data/portfolio.ts +++ b/src/data/portfolio.ts @@ -6,6 +6,7 @@ import { Link } from '../page/link/link.html'; import { Main } from '../page/main/main'; import { PageElement } from '../page/page-element'; import { TimelineElement } from '../page/timeline-element/timeline-element'; +import { UpArrowButton } from '../page/up-arrow-button/up-arrow-button'; import cvEnglish from './media/cv-andras-schmelczer.pdf'; import me from './media/me.jpg'; import { adAstra } from './projects/ad-astra'; @@ -23,51 +24,54 @@ import { sdf2d } from './projects/sdf2d'; import { towers } from './projects/towers'; import { CV, Email, GitHubLink, LinkedIn } from './shared'; +const main = new Main( + new Background(1, 1), + new Header({ + name: 'András Schmelczer', + image: me, + imageAltText: 'a picture of me', + about: [ + 'With more than six years of professional software engineering experience and a degree in Computer Science, I can confidently undertake any challenge. My interests span diverse areas, allowing me to design complex — even multidisciplinary — systems with a clear understanding.', + + "I'm passionate about architecting and building large-scale systems, especially in the context of AI/ML. However, in my free time, I also enjoy working with shaders, data visualisation, and sometimes even microcontrollers.", + + `Discover some of my more exciting projects below. And if you'd like to reach out to me, you can find my contact details at ${Link( + 'the bottom of the page', + '#contact' + )}.`, + ], + }), + + ...[ + greatAi, + declared, + sdf2d, + adAstra, + forex, + myNotes, + towers, + nuclear, + nuclearEditor, + citySimulation, + platformGame, + photos, + leds, + ].map((p) => new TimelineElement(p, 'Show details', 'Show less')), + + Contact({ + title: 'Get in touch', + links: [ + CV(cvEnglish), + Email('mailto:andras@schmelczer.dev'), + LinkedIn('https://www.linkedin.com/in/andras-schmelczer'), + GitHubLink('https://github.com/schmelczer'), + ], + lastEditText: 'Last modified on', + }) +); + export const portfolio: Array = [ - new Main( - new Background(1, 1), - new Header({ - name: 'András Schmelczer', - image: me, - imageAltText: 'a picture of me', - about: [ - 'With more than six years of professional software engineering experience and a degree in Computer Science, I can confidently undertake any challenge. My interests span diverse areas, allowing me to design complex — even multidisciplinary — systems with a clear understanding.', - - "I'm passionate about architecting and building large-scale systems, especially in the context of AI/ML. However, in my free time, I also enjoy working with shaders, data visualisation, and sometimes even microcontrollers.", - - `Discover some of my more exciting projects below. And if you'd like to reach out to me, you can find my contact details at ${Link( - 'the bottom of the page', - '#contact' - )}.`, - ], - }), - - ...[ - greatAi, - declared, - sdf2d, - adAstra, - forex, - myNotes, - towers, - nuclear, - nuclearEditor, - citySimulation, - platformGame, - photos, - leds, - ].map((p) => new TimelineElement(p, 'Show details', 'Show less')), - - Contact({ - title: 'Get in touch', - links: [ - CV(cvEnglish), - Email('mailto:andras@schmelczer.dev'), - LinkedIn('https://www.linkedin.com/in/andras-schmelczer'), - GitHubLink('https://github.com/schmelczer'), - ], - lastEditText: 'Last modified on', - }) - ), + main, new ImageViewer(), + new UpArrowButton(main, 'go up'), ]; diff --git a/src/page/up-arrow-button/up-arrow-button.html.ts b/src/page/up-arrow-button/up-arrow-button.html.ts new file mode 100644 index 0000000..9566eaa --- /dev/null +++ b/src/page/up-arrow-button/up-arrow-button.html.ts @@ -0,0 +1,9 @@ +import arrow from '../../../static/icons/arrow.svg'; +import { html } from '../../types/html'; +import './up-arrow-button.scss'; + +export const generate = (label: string): html => ` + +`; diff --git a/src/page/up-arrow-button/up-arrow-button.scss b/src/page/up-arrow-button/up-arrow-button.scss new file mode 100644 index 0000000..d9f1dcd --- /dev/null +++ b/src/page/up-arrow-button/up-arrow-button.scss @@ -0,0 +1,27 @@ +@use '../../style/mixins' as *; + +#up-arrow-button { + @include blurred-background(); + + cursor: pointer; + box-shadow: var(--shadow); + transition: opacity var(--transition-time), visibility var(--transition-time), + transform var(--transition-time); + + border-radius: var(--border-radius); + background: none; + border: none; + + position: fixed; + bottom: var(--small-margin); + right: var(--small-margin); + padding: 4px; + + &:hover { + transform: scale(1.1); + } + + svg { + @include square(var(--large-icon-size)); + } +} diff --git a/src/page/up-arrow-button/up-arrow-button.ts b/src/page/up-arrow-button/up-arrow-button.ts new file mode 100644 index 0000000..9021a49 --- /dev/null +++ b/src/page/up-arrow-button/up-arrow-button.ts @@ -0,0 +1,42 @@ +import { PageElement } from '../page-element'; +import { generate } from './up-arrow-button.html'; + +export class UpArrowButton extends PageElement { + private static readonly defaultTimeToLive = 2000; + private static readonly interval = 50; + private timeToLive = 0; + + public constructor(private scrollTarget: PageElement, label: string) { + super(generate(label)); + + this.htmlRoot.addEventListener('click', this.scrollToTop.bind(this)); + + setInterval(() => { + this.timeToLive = Math.max(0, this.timeToLive - UpArrowButton.interval); + if (this.timeToLive == 0) { + this.htmlRoot.style.opacity = '0'; + this.htmlRoot.style.visibility = 'hidden'; + } + }, UpArrowButton.interval); + } + + protected initialize() { + this.scrollTarget.htmlRoot.addEventListener('scroll', () => { + this.timeToLive = UpArrowButton.defaultTimeToLive; + this.htmlRoot.style.opacity = '1'; + this.htmlRoot.style.visibility = 'visible'; + + if (this.scrollTarget.htmlRoot.scrollTop == 0) { + this.timeToLive = 0; + } + }); + } + + private scrollToTop(e: MouseEvent) { + if (this.timeToLive > 0) { + this.scrollTarget.htmlRoot.scrollTo({ top: 0, left: 0, behavior: 'smooth' }); + } else { + e.preventDefault(); + } + } +} diff --git a/static/icons/arrow.svg b/static/icons/arrow.svg new file mode 100644 index 0000000..5a39844 --- /dev/null +++ b/static/icons/arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/cancel.svg b/static/icons/cancel.svg index 75e9631..adaae0e 100644 --- a/static/icons/cancel.svg +++ b/static/icons/cancel.svg @@ -1,4 +1,4 @@ - + diff --git a/static/icons/linkedin.svg b/static/icons/linkedin.svg index b23ad4f..75bdd74 100644 --- a/static/icons/linkedin.svg +++ b/static/icons/linkedin.svg @@ -1,4 +1,4 @@ - +