176 lines
6.7 KiB
Text
176 lines
6.7 KiB
Text
---
|
|
import { getImage } from "astro:assets";
|
|
import BaseLayout from "./BaseLayout.astro";
|
|
import logoBM from "../assets/images/logo_bm.png";
|
|
import { t } from "../i18n";
|
|
import {
|
|
IconHome,
|
|
IconBriefcase,
|
|
IconSquareRSS,
|
|
IconSun,
|
|
IconMoon,
|
|
IconMagnifyingGlass,
|
|
IconTags,
|
|
IconGamepad,
|
|
IconBook,
|
|
} from "../components/icons";
|
|
|
|
type Props = {
|
|
pageTitle: string;
|
|
enablePagefind?: boolean;
|
|
class?: string;
|
|
};
|
|
|
|
const { pageTitle, enablePagefind, class: className } = Astro.props;
|
|
const logo = await getImage({ src: logoBM, width: 192 });
|
|
const currentYear = new Date().getFullYear().toString();
|
|
const isCurrentRoute = (path: string) =>
|
|
Astro.url.pathname === path || (path !== "/" && Astro.url.pathname === `${path}/`);
|
|
---
|
|
|
|
<BaseLayout pageTitle={pageTitle}>
|
|
<Fragment slot="head">
|
|
<meta property="og:title" content={pageTitle || "Bad Manners"} />
|
|
<meta property="og:url" content={Astro.url} />
|
|
<meta property="og:image" content={logo.src} />
|
|
<meta property="og:image:alt" content="Logo for Bad Manners" />
|
|
<slot name="head" />
|
|
</Fragment>
|
|
<div
|
|
class="flex flex-col bg-stone-200 text-stone-800 md:flex-row dark:bg-stone-800 dark:text-stone-200 print:bg-none"
|
|
>
|
|
<nav
|
|
class="h-card mb-4 flex shrink-0 flex-col items-center border-b-4 border-bm-400 bg-bm-300 pb-10 pt-10 text-center text-stone-900 shadow-xl md:left-0 md:mb-0 md:min-h-screen md:w-72 md:justify-self-stretch md:border-b-0 md:border-r-4 md:pt-20 dark:border-green-950 dark:bg-green-900 dark:text-stone-100 print:bg-none print:shadow-none"
|
|
>
|
|
<img
|
|
loading="eager"
|
|
src={logo.src}
|
|
alt="A pixelated metal briefcase over a background with a green gradient."
|
|
class="u-logo my-4 w-full max-w-[192px] rounded-sm border-2 border-green-800 shadow-md dark:border-green-950"
|
|
width={192}
|
|
/>
|
|
<span class="p-name mb-6 mt-4 text-3xl font-semibold">Bad Manners</span>
|
|
<ul class="flex w-[80%] max-w-sm flex-col gap-y-2 px-4 pr-8 text-left sm:pr-2">
|
|
<li>
|
|
<a class="u-url text-link group" href="https://badmanners.xyz/" data-age-restricted rel="me">
|
|
<IconHome width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Main website</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="u-url text-link group" href="/" aria-current={isCurrentRoute("/") ? "page" : undefined}>
|
|
<IconBriefcase width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Gallery</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
class="u-url text-link group"
|
|
href="/stories/1"
|
|
aria-current={isCurrentRoute("/stories/1") ? "page" : undefined}
|
|
>
|
|
<IconBook width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Stories</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="u-url text-link group" href="/games" aria-current={isCurrentRoute("/games") ? "page" : undefined}>
|
|
<IconGamepad width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Games</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="u-url text-link group" href="/tags" aria-current={isCurrentRoute("/tags") ? "page" : undefined}>
|
|
<IconTags width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Tags</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
class="u-url text-link group"
|
|
href="/search"
|
|
rel="search"
|
|
aria-current={isCurrentRoute("/search") ? "page" : undefined}
|
|
>
|
|
<IconMagnifyingGlass width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">Search</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="u-url text-link group" href="/feed.xml">
|
|
<IconSquareRSS width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" />
|
|
<span class="order-3 group-hover:underline group-focus:underline">RSS feed</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<button
|
|
data-dark-mode
|
|
style={{ display: "none" }}
|
|
class="text-link group"
|
|
aria-label={t("en", "published_content/toggle_dark_mode")}
|
|
>
|
|
<IconSun width="1.25rem" height="1.25rem" class="order-1 hidden align-text-top dark:inline" />
|
|
<IconMoon width="1.25rem" height="1.25rem" class="order-1 inline align-text-top dark:hidden" />
|
|
<span class="order-3 hidden group-hover:underline group-focus:underline dark:block" aria-hidden="true"
|
|
>Light mode</span
|
|
>
|
|
<span class="order-3 block group-hover:underline group-focus:underline dark:hidden" aria-hidden="true"
|
|
>Dark mode</span
|
|
>
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
<div class="py-6 text-center text-xs text-black dark:text-white">
|
|
<span
|
|
>© {
|
|
currentYear === "2024" ? (
|
|
<time datetime="2024">2024</time>
|
|
) : (
|
|
<>
|
|
<time datetime="2024">2024</time>–<time datetime={currentYear}>{currentYear}</time>
|
|
</>
|
|
)
|
|
} |
|
|
</span>
|
|
<a class="text-link hover:underline focus:underline" href="/licenses.toml" rel="license">Licenses</a>
|
|
</div>
|
|
</nav>
|
|
<main
|
|
class:list={[className, "ml-0 max-w-6xl px-2 pb-28 pt-4 md:px-4 lg:px-8 print:pb-0"]}
|
|
data-pagefind-body={enablePagefind ? "" : undefined}
|
|
>
|
|
<slot />
|
|
</main>
|
|
</div>
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
nav ul li a,
|
|
nav ul li button {
|
|
@apply flex w-full items-baseline justify-between;
|
|
}
|
|
|
|
nav ul li a::after,
|
|
nav ul li button::after {
|
|
@apply order-2 flex-grow self-end bg-bottom;
|
|
background: radial-gradient(circle, currentcolor 1px, transparent 1px);
|
|
background-size: 1ex 4.5px;
|
|
background-repeat: space no-repeat;
|
|
content: "";
|
|
height: 1ex;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import tippy from "tippy.js";
|
|
import "tippy.js/dist/tippy.css";
|
|
|
|
const clipboardItems = document.querySelectorAll<HTMLElement>("[data-clipboard]");
|
|
|
|
tippy(clipboardItems, {
|
|
content: (el) => (el as HTMLElement).dataset.clipboard!,
|
|
theme: "bm",
|
|
});
|
|
|
|
clipboardItems.forEach((el) => el.removeAttribute("title"));
|
|
</script>
|