dev21w36c

This commit is contained in:
Victor Westerlund 2021-09-08 10:55:51 -04:00
parent 62cdb7aae5
commit 821ed27776
10 changed files with 123 additions and 67 deletions

View file

@ -6,11 +6,13 @@ body {
body main .screen {
transition: var(--transition) transform;
transition-delay: calc(var(--transition) / 2);
}
body.modalActive main .screen {
transition: 300ms;
transform: scale(.9,.95);
body .modal.active ~ main .screen {
transition: var(--transition);
transition-delay: 1ms;
transform: scale(.95);
opacity: .5;
pointer-events: none;
}
@ -31,11 +33,6 @@ 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);

View file

@ -91,6 +91,10 @@ main.active {
flex-direction: column;
}
body.dark .screen.dark {
background-color: black;
}
.screen .content {
box-sizing: border-box;
padding: calc(var(--padding) * 1.5);

View file

@ -5,10 +5,6 @@ class Component {
constructor(tag) {
this.element = document.createElement(tag); // Root element
}
getElement() {
return this.element;
}
}
// ⬇ UI Components ⬇

View file

@ -38,6 +38,20 @@ class Debug {
card.open();
});
}
invalidCard() {
const module = import("./Modals.mjs");
const interactions = {
hello: () => {
console.log("Hello world");
}
};
module.then(modals => {
const card = new modals.Card(interactions);
card.openPage("invalid_card");
});
}
}
export default window._debug = new Debug();

View file

@ -17,12 +17,13 @@ class Modal extends Interaction {
super(interactions,element);
this.element = this.applyTemplate(element);
document.body.appendChild(this.element);
this.element.close = () => this.close(); // Bind close to element prototype
document.body.insertAdjacentElement("afterbegin",this.element);
}
// Fetch page html from "assets/pages"
async getPage(page) {
const url = `assets/pages/${page}.html`;
const url = `assets/pages/${page}`;
const response = await fetch(url);
if(!response.ok) {
throw new Error(`Modal: Failed to fetch page "${page}"`);
@ -57,18 +58,11 @@ class Modal extends Interaction {
}
open() {
document.body.classList.add("modalActive");
setTimeout(() => this.element.classList.add("active"),this.transition / 2);
}
// Close the modal and remove it from the DOM
close() {
const activeModals = document.getElementsByClassName("modal");
if(!activeModals || activeModals.length === 1) {
// Remove active effects if all modals have been closed
setTimeout(() => document.body.classList.remove("modalActive"),this.transition / 2);
}
this.element.classList.remove("active");
setTimeout(() => destroy(this.element),this.transition + 1); // Wait for transition
}
@ -90,10 +84,27 @@ export class Card extends Modal {
text: "close",
action: "close"
});
const closeButtonElement = closeButton.getElement();
this.bind(closeButtonElement);
this.inner.appendChild(closeButtonElement);
this.bind(closeButton.element);
this.inner.appendChild(closeButton.element);
}
error(message) {
const oops = document.createElement("p");
const infoButton = new Button({
text: "more info"
});
oops.classList.add("error");
oops.innerText = "🤯\nSomething went wrong";
infoButton.element.addEventListener("click",() => {
oops.innerText = "📋\n" + message;
destroy(infoButton.element);
});
this.insertElement(infoButton.element);
this.insertElement(oops);
}
// Open page from "assets/pages"
@ -107,11 +118,9 @@ export class Card extends Modal {
// 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));
this.bindAll(this.inner);
})
.catch(error => this.error(error))
.finally(() => destroy(spinner));
}
}

View file

@ -17,17 +17,31 @@ export default class Interaction extends Logging {
this.interactions = interactions;
this.attribute = "data-action"; // Target elements with this attribute
// Bind listeners to the target attribute within the provided scope
const elements = scope.querySelectorAll(`[${this.attribute}]`);
this.bindAll(scope);
}
// Bind event listeners to this element
bind(element) {
if(element.hasAttribute("data-bound") || !element.hasAttribute(this.attribute)) {
return false;
}
element.addEventListener("click",event => this.pointerEvent(event));
element.setAttribute("data-bound","");
}
// Get all elements with the target attribute in scope
getAll(scope) {
return scope.querySelectorAll(`[${this.attribute}]`);
}
// Bind listeners to all attributed elements within scope
bindAll(scope) {
const elements = this.getAll(scope);
for(const element of elements) {
this.bind(element);
}
}
bind(element) {
element.addEventListener("click",event => this.pointerEvent(event));
}
// Set the page theme color (and the theme-color meta tag)
setThemeColor(color) {
const meta = document.head.querySelector("meta[name='theme-color']");

View file

@ -23,14 +23,19 @@ const interactions = {
openContactCard: () => {
const module = import("./modules/Modals.mjs");
const interactions = {
hello: () => {
console.log("Hello world");
getContact: (event) => {
const service = event.target.getAttribute("data-value");
module.then(modals => {
event.target.closest(".modal").close();
const card = new modals.Card(interactions);
card.openPage(service);
});
}
};
module.then(modals => {
const card = new modals.Card(interactions);
card.openPage("contact_card");
card.openPage("contact");
});
}
}
@ -53,4 +58,5 @@ function updateTheme() {
// Set the current page theme, and listen for changes
theme.addEventListener("change",updateTheme);
updateTheme();
updateTheme();
window._debug.openContactsModal();

View file

@ -0,0 +1,40 @@
<style>
.contact {
display: grid;
grid-template-rows: repeat(2, 1fr);
grid-template-columns: repeat(2, 1fr);
gap: var(--padding);
}
.contact .item {
height: 140px;
border-radius: var(--border-radius);
background-color: rgba(var(--comp-inverted),.05);
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
padding: var(--padding);
}
.contact .item * {
pointer-events: none;
}
.contact .item img {
height: 70%;
}
</style>
<div class="contact">
<div class="item center" data-action="getContact" data-value="contact_signal">
<img src="assets/img/icons/signal.svg"/>
<p>Signal</p>
</div>
<div class="item center" data-action="getContact" data-value="contact_email">
<p>E-Mail</p>
</div>
<div class="item center" data-action="getContact">
<p>
</div>
<div class="item center" data-action="getContact">
</div>
</div>

View file

@ -1,27 +0,0 @@
<style>
.contact {
display: grid;
grid-template-rows: repeat(2, 1fr);
grid-template-columns: repeat(2, 1fr);
gap: var(--padding);
}
.contact .item {
height: 140px;
border-radius: var(--border-radius);
background-color: rgba(var(--comp-inverted),.05);
}
</style>
<div class="contact">
<div class="item" data-action="hello" data-value="signal">
<p>Signal</p>
</div>
<div class="item" data-action="getContact" data-value="email">
<p>E-Mail</p>
</div>
<div class="item">
<p>
</div>
<div class="item">
</div>
</div>

View file

@ -0,0 +1,3 @@
<style>
</style>
<img src="assets/img/icons/signal.svg"/>