Migrate some scripts to Alpine and add 18+ icon
This commit is contained in:
parent
dcbf094a0e
commit
328e84ccc7
20 changed files with 220 additions and 174 deletions
|
|
@ -3,100 +3,54 @@ import AgeRestrictedScriptInline from "./AgeRestrictedScriptInline.astro";
|
|||
import { IconTriangleExclamation } from "./icons";
|
||||
---
|
||||
|
||||
<div
|
||||
id="modal-age-restricted"
|
||||
class="fixed inset-0 bg-stone-100 dark:bg-stone-900"
|
||||
role="dialog"
|
||||
aria-labelledby="title-age-restricted"
|
||||
hidden
|
||||
>
|
||||
<div class="mx-auto flex min-h-screen max-w-3xl flex-col items-center justify-center text-center tracking-tight">
|
||||
<div class="text-bm-500 dark:text-bm-400">
|
||||
<IconTriangleExclamation width="3rem" height="3rem" />
|
||||
</div>
|
||||
<div
|
||||
id="title-age-restricted"
|
||||
class="pb-3 pt-2 text-3xl font-light text-stone-700 sm:pb-4 sm:pt-2 dark:text-stone-50"
|
||||
>
|
||||
Age verification
|
||||
</div>
|
||||
<div
|
||||
class="mx-6 mb-4 max-w-xl border-b border-stone-300 pb-4 text-xl text-stone-700 dark:border-stone-300 dark:text-stone-50"
|
||||
>
|
||||
You must be 18+ to access this page.
|
||||
</div>
|
||||
<p class="px-8 text-lg font-light leading-snug text-stone-700 sm:max-w-2xl dark:text-stone-50">
|
||||
By confirming that you are at least 18 years old, your selection will be saved to your browser to prevent this
|
||||
screen from appearing in the future.
|
||||
</p>
|
||||
<div
|
||||
id="age-verification-button-list"
|
||||
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"
|
||||
hidden
|
||||
>
|
||||
<button
|
||||
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"
|
||||
<template x-if="!ageVerified">
|
||||
<div
|
||||
id="modal-age-restricted"
|
||||
class="fixed inset-0 bg-stone-100 dark:bg-stone-900"
|
||||
role="dialog"
|
||||
aria-labelledby="title-age-restricted"
|
||||
>
|
||||
<div class="mx-auto flex min-h-screen max-w-3xl flex-col items-center justify-center text-center tracking-tight">
|
||||
<div class="text-bm-500 dark:text-bm-400">
|
||||
<IconTriangleExclamation width="3rem" height="3rem" />
|
||||
</div>
|
||||
<div
|
||||
id="title-age-restricted"
|
||||
class="pb-3 pt-2 text-3xl font-light text-stone-700 sm:pb-4 sm:pt-2 dark:text-stone-50"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
Age verification
|
||||
</div>
|
||||
<div
|
||||
class="mx-6 mb-4 max-w-xl border-b border-stone-300 pb-4 text-xl text-stone-700 dark:border-stone-300 dark:text-stone-50"
|
||||
>
|
||||
I'm at least 18 years old
|
||||
</button>
|
||||
You must be 18+ to access this page.
|
||||
</div>
|
||||
<p class="px-8 text-lg font-light leading-snug text-stone-700 sm:max-w-2xl dark:text-stone-50">
|
||||
By confirming that you are at least 18 years old, your selection will be saved to your browser to prevent this
|
||||
screen from appearing in the future.
|
||||
</p>
|
||||
<div
|
||||
id="age-verification-button-list"
|
||||
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"
|
||||
hidden
|
||||
>
|
||||
<button
|
||||
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"
|
||||
@click="location.href = 'about:blank'"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
@click="localStorage.ageVerified = 'true'; ageVerified = true"
|
||||
>
|
||||
I'm at least 18 years old
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<AgeRestrictedScriptInline />
|
||||
|
||||
<script>
|
||||
const ageRestrictedModalSetup = () => {
|
||||
const modal = document.querySelector<HTMLElementTagNameMap["div"]>("div#modal-age-restricted");
|
||||
if (!modal) {
|
||||
// Not an age-restricted page
|
||||
return;
|
||||
}
|
||||
if (modal !== document.querySelector("body>div#modal-age-restricted")) {
|
||||
throw new Error("#modal-age-restricted must be a direct child of the body element!");
|
||||
}
|
||||
const addAgeVerifiedQueryToLinks = () =>
|
||||
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.toString();
|
||||
});
|
||||
if (localStorage.ageVerified === "true") {
|
||||
addAgeVerifiedQueryToLinks();
|
||||
} else {
|
||||
const rejectButton = modal.querySelector<HTMLElementTagNameMap["button"]>("button[data-modal-reject]")!;
|
||||
const onRejectButtonClick = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
location.href = "about:blank";
|
||||
};
|
||||
rejectButton.addEventListener("click", onRejectButtonClick);
|
||||
const acceptButton = modal.querySelector<HTMLElementTagNameMap["button"]>("button[data-modal-accept]")!;
|
||||
acceptButton.addEventListener(
|
||||
"click",
|
||||
(e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
rejectButton.removeEventListener("click", onRejectButtonClick);
|
||||
localStorage.ageVerified = "true";
|
||||
document.body.style.overflow = "auto";
|
||||
document.querySelectorAll("body>:not(#modal-age-restricted)").forEach((el) => el.removeAttribute("inert"));
|
||||
modal.hidden = true;
|
||||
addAgeVerifiedQueryToLinks();
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
modal.querySelector<HTMLElementTagNameMap["div"]>("div#age-verification-button-list")!.hidden = false;
|
||||
rejectButton.focus();
|
||||
}
|
||||
};
|
||||
|
||||
ageRestrictedModalSetup();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
---
|
||||
|
||||
<script is:inline>(a=>{let b="body>",c="#modal-age-restricted",d="true",e="ageVerified",f="searchParams",g=localStorage,h=new URL(location),i=x=>a.querySelectorAll(x),j=i(b+c)[0];h[f].get(e)==d&&(g[e]=d,h[f].delete(e),history.replaceState({},"",h));j&&g[e]!=d&&((a.body.style.overflow="hidden"),i(b+":not("+c+")").forEach(x=>x.setAttribute("inert",d)),(j.hidden=!1))})(document)</script>
|
||||
<script is:inline>(()=>{let a="true",b="ageVerified",c="searchParams",d=localStorage,e=new URL(location);e[c].get(b)==a&&(d[b]=a,e[c].delete(b),history.replaceState({},"",e))})()</script>
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
import DarkModeScriptInline from "./DarkModeScriptInline.astro";
|
||||
---
|
||||
|
||||
<DarkModeScriptInline />
|
||||
|
||||
<script>
|
||||
type ColorScheme = "auto" | "dark" | "light" | undefined;
|
||||
|
||||
const colorSchemeSetup = () => {
|
||||
let colorScheme: ColorScheme = localStorage.colorScheme;
|
||||
if (!colorScheme || colorScheme === "auto") {
|
||||
colorScheme = matchMedia("(prefers-color-scheme:dark)").matches ? "dark" : "light";
|
||||
}
|
||||
const toggleColorScheme = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
if (colorScheme === "dark") {
|
||||
colorScheme = "light";
|
||||
document.body.classList.remove("dark");
|
||||
} else {
|
||||
colorScheme = "dark";
|
||||
document.body.classList.add("dark");
|
||||
}
|
||||
localStorage.colorScheme = colorScheme;
|
||||
};
|
||||
document.querySelectorAll<HTMLElementTagNameMap["button"]>("button[data-dark-mode]").forEach((button) => {
|
||||
button.addEventListener("click", toggleColorScheme);
|
||||
button.classList.remove("hidden");
|
||||
button.hidden = false;
|
||||
button.setAttribute("aria-hidden", "false");
|
||||
});
|
||||
};
|
||||
|
||||
colorSchemeSetup();
|
||||
</script>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
---
|
||||
|
||||
<script is:inline>(a=>{var b="dark",c="colorScheme",d=localStorage,e=d[c];(e=="auto"||!e?matchMedia("(prefers-color-scheme:dark)").matches:e==b)&&a.body.classList.add(b)})(document)</script>
|
||||
<script is:inline>let g=document,f=a=>{var b="dark",c=localStorage,d=c.colorScheme;(d!="light"&&(d==b||matchMedia("(prefers-color-scheme:dark)").matches))&&a.body.classList.add(b)};g.addEventListener('astro:before-swap',e=>f(e.newDocument));f(g)</script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
type Props = {
|
||||
id: number;
|
||||
id: number | string;
|
||||
title: string;
|
||||
text: string;
|
||||
};
|
||||
|
|
@ -12,6 +12,6 @@ const { id, title, text } = Astro.props;
|
|||
<a class="decoration-dotted" id={`note-${id}`} href={`#note-${id}`} title={title} data-tooltip>
|
||||
{text}
|
||||
</a>
|
||||
<sup>{id}</sup>
|
||||
<em class="sr-only">({title})</em>
|
||||
{Number.isInteger(id) ? <sup>{id}</sup> : null}
|
||||
<em class="sr-only"> ({title})</em>
|
||||
</Fragment>
|
||||
|
|
|
|||
20
src/components/icons/IconNoOneUnder18.astro
Normal file
20
src/components/icons/IconNoOneUnder18.astro
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import SVGIcon from "./SVGIcon.astro";
|
||||
|
||||
type Props = {
|
||||
width: string;
|
||||
height: string;
|
||||
class?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<SVGIcon {...Astro.props} viewBox="0 0 36 36" aria-label="🔞">
|
||||
<path fill="#000000" d="M34.999 17.999c0 9.389-7.611 17-17 17s-17-7.611-17-17 7.611-17 17-17 17 7.611 17 17"
|
||||
></path><path
|
||||
fill="#F5F8FA"
|
||||
d="M9.521 12.245H7.85c-1.358 0-1.924-.991-1.924-1.953 0-.99.707-1.952 1.924-1.952h4.019c1.217 0 1.896.876 1.896 2.007v16.104c0 1.414-.906 2.207-2.122 2.207-1.216 0-2.122-.793-2.122-2.207V12.245zm7.307 10.13c0-2.264 1.245-3.934 3.027-4.895-1.33-.963-2.15-2.265-2.15-4.047 0-3.312 2.745-5.434 6.112-5.434 3.283 0 6.14 2.093 6.14 5.434 0 1.583-.791 3.17-2.178 4.047 1.924.96 3.027 2.715 3.027 4.895 0 3.934-3.197 6.451-6.989 6.451-3.906 0-6.989-2.658-6.989-6.451zm4.413-.283c0 1.443.849 2.832 2.575 2.832 1.612 0 2.576-1.389 2.576-2.832 0-1.783-1.02-2.83-2.576-2.83-1.641 0-2.575 1.246-2.575 2.83zm.538-8.206c0 1.274.736 2.151 2.037 2.151 1.302 0 2.066-.877 2.066-2.151 0-1.217-.736-2.151-2.066-2.151-1.33 0-2.037.934-2.037 2.151z"
|
||||
></path><path
|
||||
fill="#DD2E44"
|
||||
d="M18 0C8.059 0 0 8.06 0 18c0 9.941 8.059 18 18 18s18-8.059 18-18c0-9.94-8.059-18-18-18zm16 18c0 3.969-1.453 7.592-3.845 10.389L7.612 5.845C10.409 3.453 14.032 2 18 2c8.837 0 16 7.164 16 16zM2 18c0-3.968 1.453-7.591 3.844-10.387l22.543 22.543C25.591 32.548 21.968 34 18 34 9.164 34 2 26.837 2 18z"
|
||||
></path>
|
||||
</SVGIcon>
|
||||
|
|
@ -10,6 +10,7 @@ export { default as IconGamepad } from "./IconGamepad.astro";
|
|||
export { default as IconHome } from "./IconHome.astro";
|
||||
export { default as IconMagnifyingGlass } from "./IconMagnifyingGlass.astro";
|
||||
export { default as IconMoon } from "./IconMoon.astro";
|
||||
export { default as IconNoOneUnder18 } from "./IconNoOneUnder18.astro";
|
||||
export { default as IconRetweet } from "./IconRetweet.astro";
|
||||
export { default as IconSquareRSS } from "./IconSquareRSS.astro";
|
||||
export { default as IconStar } from "./IconStar.astro";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue