Add loading indicator and improve non-clipboard interactions

This commit is contained in:
Bad Manners 2024-09-23 11:26:24 -03:00
parent 66f6f52773
commit aa5759d6f5
4 changed files with 73 additions and 20 deletions

View file

@ -1,7 +1,15 @@
---
import { readFile } from "node:fs/promises";
import BaseLayout from "@layouts/BaseLayout.astro";
import { IconEnvelope, IconBriefcase, IconKey, IconLink, IconCommentDots, IconSSH } from "@components/icons";
import {
IconEnvelope,
IconBriefcase,
IconKey,
IconLink,
IconCommentDots,
IconSSH,
IconSquareRSS,
} from "@components/icons";
import {
IconBluesky,
IconCodeberg,
@ -104,6 +112,21 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
<p class="sr-only select-none">Gallery on https://gallery.badmanners.xyz</p>
</a>
</li>
<li>
<a
id="gallery-feed"
class="u-url contact-link group"
type="application/rss+xml"
href="https://gallery.badmanners.xyz/feed.xml"
rel="alternate"
aria-label="Gallery feed"
title="Gallery feed"
data-tooltip
>
<IconSquareRSS height="1.75rem" width="1.75rem" class="contact-icon" />
<p class="sr-only select-none">Gallery feed</p>
</a>
</li>
<li>
<a
id="pronouns"
@ -270,6 +293,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
id="gpg"
class="u-key contact-link group"
href="/gpg.pub"
type="text/plain"
aria-label="GPG public key"
title="GPG public key"
data-tooltip
@ -439,6 +463,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
id="ssh"
class="u-key contact-link group"
href="/ssh.pub"
type="text/plain"
aria-label="SSH public key"
title="SSH public key"
data-tooltip
@ -556,12 +581,6 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
}
// Validate links
const customClipboardItems = indexLinks.querySelectorAll<HTMLElementTagNameMap["a" | "button"]>(
"li > :is(a, button)[data-clipboard]",
);
if (!customClipboardItems.length) {
console.warn("Missing custom clipboard elements in #links list.");
}
indexLinks.querySelectorAll("li > :not(a, button)").forEach((el) => {
console.warn("Element with unknown type found in #links list:", el);
});
@ -580,6 +599,12 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
// Add functionality to custom clipboard items
if ("clipboard" in navigator) {
const customClipboardItems = indexLinks.querySelectorAll<HTMLElementTagNameMap["a" | "button"]>(
"li > :is(a, button)[data-clipboard]",
);
if (!customClipboardItems.length) {
console.warn("Missing custom clipboard elements in #links list.");
}
customClipboardItems.forEach((element) => {
const label = element.dataset.noun ?? element.getAttribute("aria-label");
const clipboard = element.dataset.clipboard;
@ -587,7 +612,6 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
console.warn(`Missing "data-clipboard" field for custom clipboard element, ignoring...`, element);
return;
}
// const disabled = element.getAttribute("disabled");
element.removeAttribute("disabled");
const elementTooltip = tippy(element, {
content: label ? `${label} copied to clipboard!` : "Copied to clipboard!",
@ -603,20 +627,35 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
.then(() => elementTooltip.show())
.catch((e) => {
console.error("Unable to copy custom content to clipboard.", clipboard, e);
// Clean up clipboard logic, and revert element to original state
// element.removeEventListener("click", onClickElement);
// elementTooltip.destroy();
// if (disabled !== null) {
// element.setAttribute("disabled", disabled);
// } else {
// // Invoke default click
// element.click();
// }
});
});
};
element.addEventListener("click", onClickElement);
});
} else {
const customClipboardButtons = indexLinks.querySelectorAll<HTMLElementTagNameMap["button"]>(
"li > button[data-clipboard][disabled]",
);
customClipboardButtons.forEach((element) => {
element.removeAttribute("disabled");
const clipboard = element.dataset.clipboard;
if (!clipboard) {
console.warn(`Missing "data-clipboard" field for custom clipboard element, ignoring...`, element);
return;
}
element.removeAttribute("disabled");
const elementTooltip = tippy(element, {
content: clipboard,
trigger: "manual",
theme: "bm",
});
const onClickElement = async (ev: Event) => {
ev.preventDefault();
hideAll();
elementTooltip.show();
};
element.addEventListener("click", onClickElement);
});
}
};