diff --git a/public/assets/css/cards.css b/public/assets/css/cards.css deleted file mode 100644 index e69de29..0000000 diff --git a/public/assets/css/modal.css b/public/assets/css/modal.css index e113f6f..25ea816 100644 --- a/public/assets/css/modal.css +++ b/public/assets/css/modal.css @@ -23,7 +23,7 @@ body.modalActive main .screen { top: 0; left: 0; width: 100vw; - height: 100vh; + height: 100%; z-index: 1; pointer-events: none; box-sizing: border-box; @@ -31,13 +31,46 @@ body.modalActive main .screen { padding: var(--padding); } +.modal + .modal { + transition: var(--transition) backdrop-filter; + backdrop-filter: blur(5px); +} + .modal.active { pointer-events: all; background-color: rgba(var(--comp-inverted),.4); } .modal .button { - background-color: rgba(var(--comp-inverted),.3); + background-color: rgba(var(--comp-inverted),.05); +} + +.modal .button p { + color: var(--color-inverted); +} + +.spinner.logo { + --size: 10vw; + --anim-speed: 1s; + align-self: center; + margin-top: var(--padding); + margin-left: calc((var(--size) / 2) * -1); + animation: logoSpinner var(--anim-speed) infinite alternate linear; +} + +.error { + text-align: center; + font-size: 20px; +} + +.error:first-line { + font-size: 15vw; +} + +@keyframes logoSpinner { + to { + opacity: .1; + } } /* -- Cards -- */ @@ -45,18 +78,25 @@ body.modalActive main .screen { .modal.card .inner { transition: var(--transition) transform, var(--transition) opacity; position: relative; - background-color: var(--color-contrast); + background-color: var(--color-background); width: calc(100vw - var(--padding)); - max-width: 600px; + max-width: 500px; align-self: flex-end; box-sizing: border-box; padding: var(--padding); transform: translateY(1vh); border-radius: var(--border-radius); opacity: 0; + display: flex; + flex-direction: column; + gap: var(--padding); } .modal.card.active .inner { transform: translateY(0); opacity: 1; +} + +.modal.card .button[data-action="close"] { + margin-top: auto; } \ No newline at end of file diff --git a/public/assets/js/modules/Debugging.mjs b/public/assets/js/modules/Debugging.mjs index 65dd09b..0780fca 100644 --- a/public/assets/js/modules/Debugging.mjs +++ b/public/assets/js/modules/Debugging.mjs @@ -8,15 +8,36 @@ class Debug { list() { const functions = [ "list", + "toggleMenu", "openContactsModal" ]; console.log("Available functions:",functions.map(f => `window._debug.${f}();`)); } + toggleMenu() { + document.getElementsByClassName("hamburger")[0].click(); + } + openContactsModal() { document.getElementsByClassName("hamburger")[0].click(); document.querySelector("div[data-action='openContactCard']").click(); } + + demoCard() { + const module = import("./Modals.mjs"); + const interactions = { + hello: () => { + console.log("Hello world"); + } + }; + + module.then(modals => { + const card = new modals.Card(interactions); + card.inner.style.height = "80vh"; + card.inner.insertAdjacentHTML("afterbegin","

Hello world

"); + card.open(); + }); + } } export default window._debug = new Debug(); \ No newline at end of file diff --git a/public/assets/js/modules/Modals.mjs b/public/assets/js/modules/Modals.mjs index a09bcb9..0292c3a 100644 --- a/public/assets/js/modules/Modals.mjs +++ b/public/assets/js/modules/Modals.mjs @@ -17,25 +17,25 @@ class Modal extends Interaction { super(interactions,element); this.element = this.applyTemplate(element); - this.importStyleSheet(); document.body.appendChild(this.element); } - // Import the companion CSS rules - importStyleSheet() { - let sheet = "assets/css/modal.css"; - const element = document.createElement("link"); - - // Exit if the stylesheet has already been imported - if(document.head.querySelector("link[data-async-modalcss]")) { - return false; + // Fetch page html from "assets/pages" + async getPage(page) { + const url = `assets/pages/${page}.html`; + const response = await fetch(url); + if(!response.ok) { + throw new Error(`Modal: Failed to fetch page "${page}"`); } + return response.text(); + } - // Import the stylesheet with a link tag - element.setAttribute("rel","stylesheet"); - element.setAttribute("href",sheet); - element.setAttribute("data-async-modalcss",""); - document.head.appendChild(element); + insertHTML(element) { + this.inner.insertAdjacentHTML("afterbegin",element); + } + + insertElement(element) { + this.inner.insertAdjacentElement("afterbegin",element); } // Apply a modal template to the provided element @@ -83,10 +83,6 @@ export class Card extends Modal { this.init(); } - setContent(content) { - this.element.insertAdjacentHTML("beforeend",content); - } - init(slim) { this.element.classList.add("card"); this.element.classList.add("center"); @@ -100,7 +96,22 @@ export class Card extends Modal { this.inner.appendChild(closeButtonElement); } + // Open page from "assets/pages" openPage(page) { + // Show a spinner while fetching + const spinner = document.createElement("div"); + spinner.classList = "logo spinner"; + this.insertElement(spinner); this.open(); + + // Fetch the requested page + this.getPage(page).then(html => { + this.insertHTML(html); + }).catch(error => { + const element = document.createElement("p"); + element.classList.add("error"); + element.innerText = "🤯\nSomething went wrong"; + this.insertElement(element); + }).finally(() => destroy(spinner)); } } \ No newline at end of file diff --git a/public/assets/js/modules/Preload.mjs b/public/assets/js/modules/Preload.mjs new file mode 100644 index 0000000..5418b21 --- /dev/null +++ b/public/assets/js/modules/Preload.mjs @@ -0,0 +1,42 @@ +// Copyright © Victor Westerlund - No libraries! 😲 + +// Load assets for later use on this page. +// This implements a hybrid of the link types "preload" and "prefetch" +export default class Preload { + constructor(assets) { + this.scripts = []; + this.stylesheets = []; + + // Get the type of asset from the file extension + assets.forEach(asset => { + const components = asset.split("."); + const extension = components[components.length - 1]; + switch(extension) { + case "mjs": + this.scripts.push(asset); + break; + case "css": + this.stylesheets.push(asset); + break; + } + }); + + // Append tags when DOM is ready + window.addEventListener("DOMContentLoaded",() => this.import()); + } + + import() { + this.scripts.forEach(script => { + const element = document.createElement("script"); + element.setAttribute("type","module"); + element.src = "assets/js/" + script; + document.body.appendChild(element); + }); + this.stylesheets.forEach(sheet => { + const element = document.createElement("link"); + element.setAttribute("rel","stylesheet"); + element.href = "assets/css/" + sheet; + document.head.appendChild(element); + }); + } +} \ No newline at end of file diff --git a/public/assets/js/script.js b/public/assets/js/script.js index ca0f090..b0f6106 100644 --- a/public/assets/js/script.js +++ b/public/assets/js/script.js @@ -1,7 +1,15 @@ // Copyright © Victor Westerlund - No libraries! 😲 +import { default as Preload } from "./modules/Preload.mjs"; import { default as Interaction } from "./modules/UI.mjs"; import { default as Debug } from "./modules/Debugging.mjs"; +// Load these assets when the DOM is ready (not needed right away) +const preload = new Preload([ + "modules/Modals.mjs", + "modules/Components.mjs", + "modal.css" +]); + // All default interactions const interactions = { toggleMenu: () => { diff --git a/public/assets/pages/contact_card.html b/public/assets/pages/contact_card.html index e69de29..43260e0 100644 --- a/public/assets/pages/contact_card.html +++ b/public/assets/pages/contact_card.html @@ -0,0 +1,27 @@ + +
+
+

Signal

+
+
+

E-Mail

+
+
+

+

+
+
+
\ No newline at end of file diff --git a/public/index.html b/public/index.html index 7dd7330..d9056a7 100644 --- a/public/index.html +++ b/public/index.html @@ -3,12 +3,15 @@ + Victor Westerlund + - + + + - Victor Westerlund