Improve tooltips with Alpine
This commit is contained in:
parent
4d3ba2776c
commit
6c834dd58a
6 changed files with 101 additions and 154 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "badmanners.xyz",
|
"name": "badmanners.xyz",
|
||||||
"version": "2.1.16",
|
"version": "2.1.17",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "badmanners.xyz",
|
"name": "badmanners.xyz",
|
||||||
"version": "2.1.16",
|
"version": "2.1.17",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/alpinejs": "^0.4.0",
|
"@astrojs/alpinejs": "^0.4.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "badmanners.xyz",
|
"name": "badmanners.xyz",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.1.16",
|
"version": "2.1.17",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "astro sync",
|
"postinstall": "astro sync",
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
|
|
|
||||||
21
src/components/EnhancedTooltips.astro
Normal file
21
src/components/EnhancedTooltips.astro
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import tippy from "tippy.js";
|
||||||
|
import "tippy.js/dist/tippy.css";
|
||||||
|
|
||||||
|
const initTooltips = () => {
|
||||||
|
const tooltipItems = document.querySelectorAll<HTMLElement>("[title][data-tooltip]");
|
||||||
|
tooltipItems.forEach((el) => el.setAttribute("data-tooltip", el.title));
|
||||||
|
tippy(tooltipItems, {
|
||||||
|
content: (el) => (el as HTMLElement).dataset.tooltip!,
|
||||||
|
theme: "bm",
|
||||||
|
});
|
||||||
|
tooltipItems.forEach((el) => el.removeAttribute("title"));
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("astro:page-load", initTooltips);
|
||||||
|
initTooltips();
|
||||||
|
</script>
|
||||||
|
|
@ -3,6 +3,7 @@ import { Image } from "astro:assets";
|
||||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||||
import { IconArrowUpRightFromSquare } from "@components/icons";
|
import { IconArrowUpRightFromSquare } from "@components/icons";
|
||||||
import { ImageSamStickerJuicebox } from "@assets/images";
|
import { ImageSamStickerJuicebox } from "@assets/images";
|
||||||
|
import EnhancedTooltips from "@components/EnhancedTooltips.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout pageTitle="About me">
|
<BaseLayout pageTitle="About me">
|
||||||
|
|
@ -65,20 +66,4 @@ import { ImageSamStickerJuicebox } from "@assets/images";
|
||||||
</article>
|
</article>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
<script>
|
<EnhancedTooltips />
|
||||||
import tippy from "tippy.js";
|
|
||||||
import "tippy.js/dist/tippy.css";
|
|
||||||
|
|
||||||
const initTooltips = () => {
|
|
||||||
const tooltipItems = document.querySelectorAll<HTMLElement>("[title][data-tooltip]");
|
|
||||||
tooltipItems.forEach((el) => el.setAttribute("data-tooltip", el.title));
|
|
||||||
tippy(tooltipItems, {
|
|
||||||
content: (el) => (el as HTMLElement).dataset.tooltip!,
|
|
||||||
theme: "bm",
|
|
||||||
});
|
|
||||||
tooltipItems.forEach((el) => el.removeAttribute("title"));
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("astro:page-load", initTooltips);
|
|
||||||
initTooltips();
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,12 @@ import {
|
||||||
IconWeasyl,
|
IconWeasyl,
|
||||||
IconYouTube,
|
IconYouTube,
|
||||||
} from "@components/icons/brands";
|
} from "@components/icons/brands";
|
||||||
|
import EnhancedTooltips from "@components/EnhancedTooltips.astro";
|
||||||
|
|
||||||
const gpgKey = await readFile("./public/gpg.pub", { encoding: "utf-8" });
|
const [gpgKey, sshKey] = await Promise.all([
|
||||||
const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
readFile("./public/gpg.pub", { encoding: "utf-8" }),
|
||||||
|
readFile("./public/ssh.pub", { encoding: "utf-8" }),
|
||||||
|
]);
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
|
|
@ -80,7 +83,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
Astro.site ? (
|
Astro.site ? (
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="permalink"
|
id="permalink"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -88,8 +91,8 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
aria-label="Permalink"
|
aria-label="Permalink"
|
||||||
title="Permalink"
|
title="Permalink"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard={Astro.site}
|
x-data={`{ clipboard: ${JSON.stringify(Astro.site.toString())}, tooltip: 'URL copied to clipboard!' }`}
|
||||||
data-noun="URL"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
>
|
>
|
||||||
<IconLink height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconLink height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="sr-only select-none">https://badmanners.xyz</p>
|
<p class="sr-only select-none">https://badmanners.xyz</p>
|
||||||
|
|
@ -97,7 +100,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
</li>
|
</li>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="gallery"
|
id="gallery"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -112,7 +115,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="sr-only select-none">Gallery on https://gallery.badmanners.xyz</p>
|
<p class="sr-only select-none">Gallery on https://gallery.badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="gallery-feed"
|
id="gallery-feed"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -127,7 +130,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="sr-only select-none">Gallery feed</p>
|
<p class="sr-only select-none">Gallery feed</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="pronouns"
|
id="pronouns"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -143,7 +146,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-pronoun hidden">they/them/their/theirs/themself</p>
|
<p class="p-pronoun hidden">they/them/their/theirs/themself</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="e-mail"
|
id="e-mail"
|
||||||
class="u-email contact-link group"
|
class="u-email contact-link group"
|
||||||
|
|
@ -152,14 +155,14 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
aria-label="E-mail"
|
aria-label="E-mail"
|
||||||
title="E-mail"
|
title="E-mail"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard="me@badmanners.xyz"
|
x-data="{ clipboard: 'me@badmanners.xyz', tooltip: 'E-mail address copied to clipboard!' }"
|
||||||
data-noun="E-mail address"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
>
|
>
|
||||||
<IconEnvelope height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconEnvelope height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="sr-only select-none">me@badmanners.xyz</p>
|
<p class="sr-only select-none">me@badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="bluesky"
|
id="bluesky"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -173,7 +176,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">@badmanners.xyz on Bluesky</p>
|
<p class="p-nickname sr-only select-none">@badmanners.xyz on Bluesky</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="codeberg"
|
id="codeberg"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -187,22 +190,21 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Codeberg</p>
|
<p class="p-nickname sr-only select-none">BadManners on Codeberg</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<button
|
<button
|
||||||
id="discord"
|
id="discord"
|
||||||
class="text-link group block w-full py-2 transition-colors motion-reduce:transition-none"
|
class="text-link group block w-full py-2 transition-colors motion-reduce:transition-none"
|
||||||
aria-label="Discord"
|
aria-label="Discord"
|
||||||
title="Discord"
|
title="Discord"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard="badmanners"
|
x-data="{ clipboard: 'badmanners', tooltip: 'Discord username copied to clipboard!' }"
|
||||||
data-noun="Discord username"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
disabled
|
|
||||||
>
|
>
|
||||||
<IconDiscord height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconDiscord height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="p-nickname sr-only select-none">badmanners on Discord</p>
|
<p class="p-nickname sr-only select-none">badmanners on Discord</p>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="eka-s-portal"
|
id="eka-s-portal"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -216,7 +218,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Eka's Portal</p>
|
<p class="p-nickname sr-only select-none">BadManners on Eka's Portal</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="fur-affinity"
|
id="fur-affinity"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -230,7 +232,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Fur Affinity</p>
|
<p class="p-nickname sr-only select-none">BadManners on Fur Affinity</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="gitgud"
|
id="gitgud"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -244,7 +246,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitGud</p>
|
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitGud</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="github"
|
id="github"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -258,7 +260,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitHub</p>
|
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitHub</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="gitlab"
|
id="gitlab"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -272,7 +274,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">Bad_Manners on GitLab</p>
|
<p class="p-nickname sr-only select-none">Bad_Manners on GitLab</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="google"
|
id="google"
|
||||||
class="u-email contact-link group"
|
class="u-email contact-link group"
|
||||||
|
|
@ -281,14 +283,14 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
aria-label="Google"
|
aria-label="Google"
|
||||||
title="Google"
|
title="Google"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard="google@badmanners.xyz"
|
x-data="{ clipboard: 'google@badmanners.xyz', tooltip: 'Google address copied to clipboard!' }"
|
||||||
data-noun="Google address"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
>
|
>
|
||||||
<IconGoogle height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconGoogle height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="sr-only select-none">google@badmanners.xyz</p>
|
<p class="sr-only select-none">google@badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="gpg"
|
id="gpg"
|
||||||
class="u-key contact-link group"
|
class="u-key contact-link group"
|
||||||
|
|
@ -297,14 +299,14 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
aria-label="GPG public key"
|
aria-label="GPG public key"
|
||||||
title="GPG public key"
|
title="GPG public key"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard={gpgKey}
|
x-data={`{ clipboard: ${JSON.stringify(gpgKey)}, tooltip: 'GPG key copied to clipboard!' }`}
|
||||||
data-noun="GPG key"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
>
|
>
|
||||||
<IconKey height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconKey height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="sr-only select-none">GPG public key</p>
|
<p class="sr-only select-none">GPG public key</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="inkbunny"
|
id="inkbunny"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -318,7 +320,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Inkbunny</p>
|
<p class="p-nickname sr-only select-none">BadManners on Inkbunny</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="itaku"
|
id="itaku"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -332,7 +334,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners on Itaku</p>
|
<p class="p-nickname sr-only select-none">badmanners on Itaku</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="itch"
|
id="itch"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -346,7 +348,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">Bad Manners on Itch.io</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on Itch.io</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="keybase"
|
id="keybase"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -360,7 +362,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners on Keybase</p>
|
<p class="p-nickname sr-only select-none">badmanners on Keybase</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="keyoxide"
|
id="keyoxide"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -374,7 +376,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-uid sr-only select-none">aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU</p>
|
<p class="p-uid sr-only select-none">aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="ko-fi"
|
id="ko-fi"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -388,7 +390,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners on Ko-fi</p>
|
<p class="p-nickname sr-only select-none">badmanners on Ko-fi</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="mastodon"
|
id="mastodon"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -402,7 +404,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">@BadManners@meow.social on Mastodon</p>
|
<p class="p-nickname sr-only select-none">@BadManners@meow.social on Mastodon</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="neocities"
|
id="neocities"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -416,7 +418,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners.neocities.org on Neocities</p>
|
<p class="p-nickname sr-only select-none">badmanners.neocities.org on Neocities</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="picarto"
|
id="picarto"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -430,7 +432,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Picarto</p>
|
<p class="p-nickname sr-only select-none">BadManners on Picarto</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="signal"
|
id="signal"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -444,7 +446,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners.10 on Signal</p>
|
<p class="p-nickname sr-only select-none">badmanners.10 on Signal</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="sofurry"
|
id="sofurry"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -458,7 +460,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">Bad Manners on SoFurry</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on SoFurry</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="ssh"
|
id="ssh"
|
||||||
class="u-key contact-link group"
|
class="u-key contact-link group"
|
||||||
|
|
@ -467,14 +469,14 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
aria-label="SSH public key"
|
aria-label="SSH public key"
|
||||||
title="SSH public key"
|
title="SSH public key"
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-clipboard={sshKey}
|
x-data={`{ clipboard: ${JSON.stringify(sshKey)}, tooltip: 'SSH key address copied to clipboard!' }`}
|
||||||
data-noun="SSH key"
|
@click.prevent="navigator.clipboard.writeText(clipboard).catch(()=>{}); $dispatch('tippyTooltip', { target: $el, content: tooltip })"
|
||||||
>
|
>
|
||||||
<IconSSH height="1.75rem" width="1.75rem" class="contact-icon" />
|
<IconSSH height="1.75rem" width="1.75rem" class="contact-icon" />
|
||||||
<p class="sr-only select-none">SSH public key</p>
|
<p class="sr-only select-none">SSH public key</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="steam"
|
id="steam"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -488,7 +490,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">badmanners_ on Steam</p>
|
<p class="p-nickname sr-only select-none">badmanners_ on Steam</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="subscribestar"
|
id="subscribestar"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -502,7 +504,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">Bad Manners on SubscribeStar</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on SubscribeStar</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="telegram"
|
id="telegram"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -516,7 +518,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">@bad_manners on Telegram</p>
|
<p class="p-nickname sr-only select-none">@bad_manners on Telegram</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="twitch"
|
id="twitch"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -530,7 +532,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">bad__manners on Twitch</p>
|
<p class="p-nickname sr-only select-none">bad__manners on Twitch</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="weasyl"
|
id="weasyl"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -544,7 +546,7 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
<p class="p-nickname sr-only select-none">BadManners on Weasyl</p>
|
<p class="p-nickname sr-only select-none">BadManners on Weasyl</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-link>
|
<li>
|
||||||
<a
|
<a
|
||||||
id="youtube"
|
id="youtube"
|
||||||
class="u-url contact-link group"
|
class="u-url contact-link group"
|
||||||
|
|
@ -570,85 +572,39 @@ const sshKey = await readFile("./public/ssh.pub", { encoding: "utf-8" });
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<EnhancedTooltips />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import tippy, { hideAll } from "tippy.js";
|
import tippy, { hideAll } from "tippy.js";
|
||||||
import "tippy.js/dist/tippy.css";
|
import "tippy.js/dist/tippy.css";
|
||||||
|
|
||||||
const initIndexIcons = () => {
|
const handleTooltipEvent = () => {
|
||||||
const indexLinks = document.querySelector<HTMLElementTagNameMap["ul"]>("ul#links");
|
const indexLinks = document.querySelector<HTMLElementTagNameMap["ul"]>("ul#links");
|
||||||
if (!indexLinks) {
|
if (!indexLinks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate hover tooltips
|
interface TippyTooltipEvent extends Event {
|
||||||
const tooltipItems = document.querySelectorAll<HTMLElement>("[title][data-tooltip]");
|
detail: {
|
||||||
tooltipItems.forEach((el) => el.setAttribute("data-tooltip", el.title));
|
target: HTMLElement;
|
||||||
tippy(tooltipItems, {
|
content: string;
|
||||||
content: (el) => (el as HTMLElement).dataset.tooltip!,
|
};
|
||||||
theme: "bm",
|
|
||||||
});
|
|
||||||
tooltipItems.forEach((el) => el.removeAttribute("title"));
|
|
||||||
|
|
||||||
// Add functionality to custom clipboard items
|
|
||||||
if ("clipboard" in navigator) {
|
|
||||||
const customClipboardItems = document.querySelectorAll<HTMLElement>("ul#links li[data-link] [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;
|
|
||||||
if (!clipboard) {
|
|
||||||
console.warn(`Missing "data-clipboard" field for custom clipboard element, ignoring...`, element);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
element.removeAttribute("disabled");
|
|
||||||
const elementTooltip = tippy(element, {
|
|
||||||
content: label ? `${label} copied to clipboard!` : "Copied to clipboard!",
|
|
||||||
trigger: "manual",
|
|
||||||
theme: "bm",
|
|
||||||
});
|
|
||||||
const onClickElement = async (ev: Event) => {
|
|
||||||
ev.preventDefault();
|
|
||||||
hideAll();
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
navigator.clipboard
|
|
||||||
.writeText(clipboard)
|
|
||||||
.then(() => elementTooltip.show())
|
|
||||||
.catch((e) => {
|
|
||||||
console.error("Unable to copy custom content to clipboard.", clipboard, e);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
element.addEventListener("click", onClickElement);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const customClipboardButtons = document.querySelectorAll<HTMLElementTagNameMap["button"]>(
|
|
||||||
"ul#links li[data-link] button[data-clipboard]",
|
|
||||||
);
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener("tippyTooltip", (e: Event) => {
|
||||||
|
const { target, content } = (e as TippyTooltipEvent).detail;
|
||||||
|
hideAll();
|
||||||
|
const tooltip = tippy(target, {
|
||||||
|
content,
|
||||||
|
theme: "bm",
|
||||||
|
onHidden(instance) {
|
||||||
|
instance.destroy();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
tooltip.show();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("astro:page-load", initIndexIcons);
|
document.addEventListener("astro:page-load", handleTooltipEvent);
|
||||||
initIndexIcons();
|
handleTooltipEvent();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Image } from "astro:assets";
|
||||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||||
import { IconArrowUpRightFromSquare } from "@components/icons";
|
import { IconArrowUpRightFromSquare } from "@components/icons";
|
||||||
import { ImageSamAllStickers, ImageSamRefsheet } from "@assets/images";
|
import { ImageSamAllStickers, ImageSamRefsheet } from "@assets/images";
|
||||||
|
import EnhancedTooltips from "@components/EnhancedTooltips.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout pageTitle="Sam Brendan">
|
<BaseLayout pageTitle="Sam Brendan">
|
||||||
|
|
@ -195,20 +196,4 @@ import { ImageSamAllStickers, ImageSamRefsheet } from "@assets/images";
|
||||||
</article>
|
</article>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
<script>
|
<EnhancedTooltips />
|
||||||
import tippy from "tippy.js";
|
|
||||||
import "tippy.js/dist/tippy.css";
|
|
||||||
|
|
||||||
const initTooltips = () => {
|
|
||||||
const tooltipItems = document.querySelectorAll<HTMLElement>("[title][data-tooltip]");
|
|
||||||
tooltipItems.forEach((el) => el.setAttribute("data-tooltip", el.title));
|
|
||||||
tippy(tooltipItems, {
|
|
||||||
content: (el) => (el as HTMLElement).dataset.tooltip!,
|
|
||||||
theme: "bm",
|
|
||||||
});
|
|
||||||
tooltipItems.forEach((el) => el.removeAttribute("title"));
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("astro:page-load", initTooltips);
|
|
||||||
initTooltips();
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue