diff --git a/package-lock.json b/package-lock.json
index 9f1772e..357b8c0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "badmanners.xyz",
- "version": "2.1.14",
+ "version": "2.1.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "badmanners.xyz",
- "version": "2.1.14",
+ "version": "2.1.15",
"hasInstallScript": true,
"dependencies": {
"@astrojs/check": "^0.9.3",
@@ -14,6 +14,7 @@
"@astrojs/tailwind": "^5.1.0",
"astro": "^4.15.5",
"astro-htaccess": "^0.2.0",
+ "astro-loading-indicator": "^0.6.0",
"date-fns": "^3.6.0",
"tailwindcss": "^3.4.11",
"tippy.js": "^6.3.7",
@@ -2394,6 +2395,15 @@
"astro": "^4.0.0"
}
},
+ "node_modules/astro-loading-indicator": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/astro-loading-indicator/-/astro-loading-indicator-0.6.0.tgz",
+ "integrity": "sha512-0/gJ94ygnZ+qnLeP+dapOwAmj74hRP6t4o784+W41TicCp3pPm3d+WoH7XHlSQlokghtVynD9RdFjRd0ZWs9bg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "astro": "^4.0.0"
+ }
+ },
"node_modules/autoprefixer": {
"version": "10.4.18",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
diff --git a/package.json b/package.json
index 70f1a3e..9dd75f0 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "badmanners.xyz",
"type": "module",
- "version": "2.1.14",
+ "version": "2.1.15",
"scripts": {
"postinstall": "astro sync",
"dev": "astro dev",
@@ -20,6 +20,7 @@
"@astrojs/tailwind": "^5.1.0",
"astro": "^4.15.5",
"astro-htaccess": "^0.2.0",
+ "astro-loading-indicator": "^0.6.0",
"date-fns": "^3.6.0",
"tailwindcss": "^3.4.11",
"tippy.js": "^6.3.7",
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index 770ddd9..9f59cd8 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -1,5 +1,6 @@
---
import { ViewTransitions } from "astro:transitions";
+import LoadingIndicator from "astro-loading-indicator/component";
import DarkModeScript from "@components/DarkModeScript.astro";
import NavHeader from "@components/NavHeader.astro";
import { IconSun, IconMoon } from "@components/icons";
@@ -28,11 +29,13 @@ const title = pageTitle ? `${pageTitle} | Bad Manners` : "Bad Manners";
{title}
+
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 9ca7894..bc5f6d9 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -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" });
Gallery on https://gallery.badmanners.xyz
+
+
+
+ Gallery feed
+
+
(
- "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(
+ "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(
+ "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);
+ });
}
};