Improve age-restricted hyperlinks, clean up markup, and add navigation icons
This commit is contained in:
parent
c55c82633d
commit
57c2c7c649
31 changed files with 279 additions and 138 deletions
|
|
@ -28,6 +28,7 @@ import IconTriangleExclamation from "./icons/IconTriangleExclamation.astro";
|
|||
</p>
|
||||
<div class="flex w-full max-w-md flex-col-reverse justify-evenly gap-y-5 px-6 pt-5 sm:max-w-2xl sm:flex-row">
|
||||
<button
|
||||
style={{display: "none"}}
|
||||
data-modal-reject
|
||||
id="age-verification-reject"
|
||||
class="rounded bg-stone-400 py-3 text-lg text-stone-900 hover:bg-stone-500 hover:text-stone-50 focus:bg-stone-500 focus:text-stone-50 sm:px-9 dark:bg-stone-300 dark:text-stone-900 dark:hover:bg-stone-600 dark:hover:text-stone-50 dark:focus:bg-stone-600 dark:focus:text-stone-50"
|
||||
|
|
@ -35,6 +36,7 @@ import IconTriangleExclamation from "./icons/IconTriangleExclamation.astro";
|
|||
Cancel
|
||||
</button>
|
||||
<button
|
||||
style={{display: "none"}}
|
||||
data-modal-accept
|
||||
id="age-verification-accept"
|
||||
class="rounded bg-bm-500 py-3 text-lg text-stone-900 hover:bg-stone-500 hover:text-stone-50 focus:bg-stone-500 focus:text-stone-50 sm:px-9 dark:bg-bm-400 dark:text-stone-900 dark:hover:bg-stone-600 dark:hover:text-stone-50 dark:focus:bg-stone-600 dark:focus:text-stone-50"
|
||||
|
|
@ -49,13 +51,18 @@ import IconTriangleExclamation from "./icons/IconTriangleExclamation.astro";
|
|||
|
||||
<script>
|
||||
const ENABLE_VIEW_TRANSITIONS = false;
|
||||
type AgeVerified = "true" | undefined;
|
||||
|
||||
const ageRestrictedModalSetup = () => {
|
||||
const modal = document.querySelector<HTMLElementTagNameMap["div"]>("body > div#modal-age-restricted");
|
||||
const modal = document.querySelector<HTMLElementTagNameMap["div"]>("div#modal-age-restricted");
|
||||
// Not an age-restricted page
|
||||
if (!modal) {
|
||||
throw new Error("Missing #modal-age-restricted element! Make sure that it's a direct child of body.");
|
||||
return;
|
||||
}
|
||||
let ageVerified: "true" | undefined = localStorage.ageVerified;
|
||||
if (modal !== document.querySelector("body > div#modal-age-restricted")) {
|
||||
throw new Error("#modal-age-restricted must be a direct child of the body element!");
|
||||
}
|
||||
let ageVerified: AgeVerified = localStorage.ageVerified;
|
||||
if (ageVerified !== "true") {
|
||||
const rejectButton = modal.querySelector<HTMLElementTagNameMap["button"]>("button[data-modal-reject]")!;
|
||||
const onRejectButtonClick = (e: MouseEvent) => {
|
||||
|
|
@ -63,7 +70,9 @@ import IconTriangleExclamation from "./icons/IconTriangleExclamation.astro";
|
|||
location.href = "about:blank";
|
||||
};
|
||||
rejectButton.addEventListener("click", onRejectButtonClick);
|
||||
modal.querySelector<HTMLElementTagNameMap["button"]>("button[data-modal-accept]")!.addEventListener(
|
||||
rejectButton.style.removeProperty("display");
|
||||
const acceptButton = modal.querySelector<HTMLElementTagNameMap["button"]>("button[data-modal-accept]")!;
|
||||
acceptButton.addEventListener(
|
||||
"click",
|
||||
(e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -72,10 +81,16 @@ import IconTriangleExclamation from "./icons/IconTriangleExclamation.astro";
|
|||
localStorage.ageVerified = ageVerified;
|
||||
document.body.style.overflow = "auto";
|
||||
document.querySelectorAll("body > :not(#modal-age-restricted)").forEach((el) => el.removeAttribute("inert"));
|
||||
document.body.querySelectorAll<HTMLElementTagNameMap["a"]>("a[href][data-age-restricted]").forEach((el) => {
|
||||
let newHref = new URL(el.href);
|
||||
newHref.searchParams.set("ageVerified", "true");
|
||||
el.href = newHref.href;
|
||||
});
|
||||
modal.style.display = "none";
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
acceptButton.style.removeProperty("display");
|
||||
rejectButton.focus();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
---
|
||||
|
||||
<script is:inline>function a(){let b=document,c="#modal-age-restricted",d="true";localStorage.ageVerified!==d&&((b.body.style.overflow="hidden"),b.querySelectorAll("body > :not("+c+")").forEach(e=>e.setAttribute("inert",d)),(b.querySelector("body > "+c).style.display="block"));}document.addEventListener("astro:after-swap",a);a()</script>
|
||||
<script is:inline>function a(){let b=document,c="#modal-age-restricted",d="true",e=b.querySelector("body > "+c),f="ageVerified",g="searchParams",h=localStorage;new URL(b.location)[g].get(f)===d&&(h[f]=d);e&&(h[f]===d?b.querySelectorAll("a[href][data-age-restricted]").forEach(x=>{let y=new URL(x.href);y[g].set(f,d);x.href=y.href}):((b.body.style.overflow="hidden"),b.querySelectorAll("body > :not("+c+")").forEach(x=>x.setAttribute("inert",d)),(e.style.display="block")))};document.addEventListener("astro:after-swap",a);a()</script>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const charactersPerUser = copyrightedCharacters ? await formatCopyrightedCharact
|
|||
t(lang, "characters/characters_are_copyrighted_by", user, characters[0] === "" ? [] : characters)
|
||||
}
|
||||
>
|
||||
<UserComponent class="p-name" lang={lang} user={user} />
|
||||
<UserComponent lang={lang} user={user} />
|
||||
</CopyrightedCharactersItem>
|
||||
))}
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import DarkModeScriptInline from "./DarkModeScriptInline.astro";
|
|||
|
||||
<script>
|
||||
const ENABLE_VIEW_TRANSITIONS = false;
|
||||
type ColorScheme = "auto" | "dark" | "light";
|
||||
type ColorScheme = "auto" | "dark" | "light" | undefined;
|
||||
|
||||
const colorSchemeSetup = () => {
|
||||
let colorScheme: ColorScheme | undefined = localStorage.colorScheme;
|
||||
let colorScheme: ColorScheme = localStorage.colorScheme;
|
||||
if (!colorScheme || colorScheme === "auto") {
|
||||
colorScheme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
|
|
@ -25,10 +25,10 @@ import DarkModeScriptInline from "./DarkModeScriptInline.astro";
|
|||
localStorage.colorScheme = colorScheme;
|
||||
};
|
||||
document.querySelectorAll<HTMLElementTagNameMap["button"]>("button[data-dark-mode]").forEach((button) => {
|
||||
button.addEventListener("click", toggleColorScheme);
|
||||
button.classList.remove("hidden");
|
||||
button.style.removeProperty("display");
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
button.addEventListener("click", toggleColorScheme);
|
||||
});
|
||||
};
|
||||
if (ENABLE_VIEW_TRANSITIONS) {
|
||||
|
|
@ -36,4 +36,4 @@ import DarkModeScriptInline from "./DarkModeScriptInline.astro";
|
|||
} else {
|
||||
colorSchemeSetup();
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ const { link, instance, user, postId } = Astro.props;
|
|||
<a
|
||||
data-author
|
||||
class="p-author h-card u-url text-link flex items-center text-lg hover:underline focus:underline"
|
||||
rel="nofollow"
|
||||
target="_blank"
|
||||
>
|
||||
<picture>
|
||||
|
|
@ -95,6 +96,7 @@ const { link, instance, user, postId } = Astro.props;
|
|||
<a
|
||||
data-post-link
|
||||
class="u-url text-link my-1 flex items-center text-sm font-light hover:underline focus:underline"
|
||||
rel="nofollow"
|
||||
target="_blank"
|
||||
>
|
||||
<time class="dt-published mr-1" data-published-date aria-label="Publish date"></time>
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
|
||||
---
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
class="hover:text-green-800 hover:underline focus:text-green-800 focus:underline dark:hover:text-bm-300 dark:focus:text-bm-300"
|
||||
href="/">Home</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="hover:text-green-800 hover:underline focus:text-green-800 focus:underline dark:hover:text-bm-300 dark:focus:text-bm-300"
|
||||
href="/stories/1">Stories</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="hover:text-green-800 hover:underline focus:text-green-800 focus:underline dark:hover:text-bm-300 dark:focus:text-bm-300"
|
||||
href="/games">Games</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="hover:text-green-800 hover:underline focus:text-green-800 focus:underline dark:hover:text-bm-300 dark:focus:text-bm-300"
|
||||
href="/tags">Tags</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="hover:text-green-800 hover:underline focus:text-green-800 focus:underline dark:hover:text-bm-300 dark:focus:text-bm-300"
|
||||
href="/search">Search</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import clsx from "clsx";
|
||||
import type { Lang } from "../i18n";
|
||||
import { getUsernameForLang } from "../utils/get_username_for_lang";
|
||||
|
||||
|
|
@ -17,10 +18,10 @@ const link = user.data.preferredLink ? user.data.links[user.data.preferredLink]!
|
|||
|
||||
{
|
||||
link ? (
|
||||
<a rel={rel} href={link} class:list={[className, "h-card u-url text-link underline"]} target="_blank">
|
||||
<a rel={clsx(rel, "nofollow")} href={link} class:list={[className, "h-card u-url p-name text-link underline"]} target="_blank">
|
||||
{username}
|
||||
</a>
|
||||
) : (
|
||||
<span class:list={[className, "h-card"]}>{username}</span>
|
||||
<span class:list={[className, "h-card p-name"]}>{username}</span>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
13
src/components/icons/IconBook.astro
Normal file
13
src/components/icons/IconBook.astro
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 448 512">
|
||||
<path d="M96 0C43 0 0 43 0 96L0 416c0 53 43 96 96 96l288 0 32 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l0-64c17.7 0 32-14.3 32-32l0-320c0-17.7-14.3-32-32-32L384 0 96 0zm0 384l256 0 0 64L96 448c-17.7 0-32-14.3-32-32s14.3-32 32-32zm32-240c0-8.8 7.2-16 16-16l192 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-192 0c-8.8 0-16-7.2-16-16zm16 48l192 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-192 0c-8.8 0-16-7.2-16-16s7.2-16 16-16z" />
|
||||
</SVGIcon>
|
||||
15
src/components/icons/IconBriefcase.astro
Normal file
15
src/components/icons/IconBriefcase.astro
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 512 512">
|
||||
<path
|
||||
d="M184 48l144 0c4.4 0 8 3.6 8 8l0 40L176 96l0-40c0-4.4 3.6-8 8-8zm-56 8l0 40L64 96C28.7 96 0 124.7 0 160l0 96 192 0 128 0 192 0 0-96c0-35.3-28.7-64-64-64l-64 0 0-40c0-30.9-25.1-56-56-56L184 0c-30.9 0-56 25.1-56 56zM512 288l-192 0 0 32c0 17.7-14.3 32-32 32l-64 0c-17.7 0-32-14.3-32-32l0-32L0 288 0 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-128z"
|
||||
></path>
|
||||
</SVGIcon>
|
||||
13
src/components/icons/IconGamepad.astro
Normal file
13
src/components/icons/IconGamepad.astro
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 640 512">
|
||||
<path d="M192 64C86 64 0 150 0 256S86 448 192 448l256 0c106 0 192-86 192-192s-86-192-192-192L192 64zM496 168a40 40 0 1 1 0 80 40 40 0 1 1 0-80zM392 304a40 40 0 1 1 80 0 40 40 0 1 1 -80 0zM168 200c0-13.3 10.7-24 24-24s24 10.7 24 24l0 32 32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0 0 32c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-32-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l32 0 0-32z" />
|
||||
</SVGIcon>
|
||||
13
src/components/icons/IconMagnifyingGlass.astro
Normal file
13
src/components/icons/IconMagnifyingGlass.astro
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 512 512">
|
||||
<path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
|
||||
</SVGIcon>
|
||||
14
src/components/icons/IconTags.astro
Normal file
14
src/components/icons/IconTags.astro
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 512 512">
|
||||
<path d="M345 39.1L472.8 168.4c52.4 53 52.4 138.2 0 191.2L360.8 472.9c-9.3 9.4-24.5 9.5-33.9 .2s-9.5-24.5-.2-33.9L438.6 325.9c33.9-34.3 33.9-89.4 0-123.7L310.9 72.9c-9.3-9.4-9.2-24.6 .2-33.9s24.6-9.2 33.9 .2zM0 229.5L0 80C0 53.5 21.5 32 48 32l149.5 0c17 0 33.3 6.7 45.3 18.7l168 168c25 25 25 65.5 0 90.5L277.3 442.7c-25 25-65.5 25-90.5 0l-168-168C6.7 262.7 0 246.5 0 229.5zM144 144a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"
|
||||
/>
|
||||
</SVGIcon>
|
||||
Loading…
Add table
Add a link
Reference in a new issue