astro/src/layouts/Blog.astro
2025-02-23 03:05:38 -05:00

377 lines
9.4 KiB
Plaintext

---
import { Image } from "astro:assets";
import { getCollection } from "astro:content";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import Layout from "./Layout.astro";
import Navbar from "@/components/Navbar.astro";
import moods from "@/utils/moods";
import outerBBS from "@/assets/guild-bbs.png";
import innerBBS from "@/assets/guild-bbs-content.png";
import sideBBS from "@/assets/guild-bbs-list.png";
interface Props {
title: string;
date: Date;
currently?: {
mood?: string;
reading?: string;
listening?: string;
watching?: string;
playing?: string;
}
}
const { title, date, currently } = Astro.props;
const blog = await getCollection("blog");
blog.length = Math.min(blog.length, 5);
blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
dayjs.extend(utc);
---
<Layout {title}>
<Navbar />
<main>
<nav id="blog-links">
<div class="inner">
<hgroup>
<h1><span class="title">recent posts</span></h1>
<ul>
{blog.map(entry => (
<li>
<span class="item">
<a href={`/blog/${entry.id}`}>{entry.data.title}</a>
<time datetime={dayjs(entry.data.pubDate!).utc(true).toISOString()}>
{dayjs(entry.data.pubDate).utc(true).format("M/D/YY")}
</time>
</span>
</li>
))}
</ul>
</hgroup>
<hgroup>
<h1><span class="title">other links</span></h1>
<ul>
<li><span class="item"><a href="/blog">archive</a></span></li>
<li><span class="item"><a href="/blog/rss.xml">rss feed</a></span></li>
</ul>
</hgroup>
</div>
</nav>
<section>
<article>
<div class="inner">
<header>
<h1>{title}</h1>
<hr />
<div class="info">
<time datetime={dayjs(date).utc(true).toISOString()}>
<span class="title">Date</span>
<span class="desc">{dayjs(date).utc(true).format("MMMM DD, YYYY")}</span>
</time>
</div>
</header>
<div class="content">
<slot />
</div>
{currently && (
<aside>
<h2>Current</h2>
{currently?.mood && (
<dl>
<dt class="title">Mood</dt>
<dd class="desc">
<Image src={`/src/assets/moods/${moods.find(mood => mood === currently?.mood)}.png`} width={36} height={36} alt="" />
{currently.mood}
</dd>
</dl>
)}
{currently.playing && (
<dl>
<dt class="title">Game</dt>
<dd class="desc">{currently.playing}</dd>
</dl>
)}
{currently.watching && (
<dl>
<dt class="title">Show</dt>
<dd class="desc">{currently.watching}</dd>
</dl>
)}
{currently.reading && (
<dl>
<dt class="title">Book</dt>
<dd class="desc">{currently.reading}</dd>
</dl>
)}
{currently.listening && (
<dl>
<dt>Currently listening</dt>
<dd>{currently.listening}</dd>
</dl>
)}
</aside>
)}
</div>
</article>
</section>
<slot name="pagination" />
</main>
</Layout>
<style define:vars={{ outerBorder: `url(${outerBBS.src})`, innerBorder: `url(${innerBBS.src})`, sideBorder: `url(${sideBBS.src})` }}>
body {
image-rendering: pixelated;
--bg-0: #fff;
--bg-1: #eeffff;
--bg-2: #eeeeff;
--bg-3: #eee;
--bg-4: #ddddee;
--bg-5: #ddeeee;
--bg-6: #ccccdd;
--bg-7: #ccddee;
--bg-8: #8888bb;
--border-0: #000;
--border-1: #334466;
--border-2: #6699aa;
--border-3: #7799bb;
--border-4: #88aabb;
--border-5: #99bbcc;
--border-6: #bbccdd;
}
h1 { font: bold 1rem var(--arial-font); }
h2 {
font: normal 1.5rem var(--mplus-12-font);
text-transform: uppercase;
}
main {
font: 1rem var(--arial-font);
display: grid;
grid-template-columns: auto minmax(auto, 75ch);
justify-content: center;
@media screen and (max-width: 1360px) {
margin: 0 1rem;
}
@media screen and (max-width: 76em) {
grid-template-columns: 1fr;
}
}
#blog-links {
min-width: 28ch;
border: 2px solid var(--border-0);
border-image: var(--sideBorder) 22 8 40 7 fill / 44px 16px 80px 14px;
background-color: var(--bg-0);
padding: 42px 10px 78px;
margin-right: -2px;
.inner {
display: flex;
height: calc(100% - 34px);
flex-flow: column wrap;
background-color: var(--bg-3);
padding: 2px;
margin: 18px 6px;
border: 2px solid var(--border-6);
}
h1 {
padding: 6px 2px;
border-block: 2px solid var(--border-3);
.title {
display: inline-block;
background-color: var(--bg-8);
color: var(--bg-0);
font-weight: normal;
text-transform: uppercase;
padding: 5px 2px;
text-align: center;
width: 100%;
}
}
ul {
display: flex;
flex-flow: column wrap;
list-style: none;
padding: 0;
li {
padding: 4px 2px;
border-bottom: 2px solid var(--bg-4);
.item {
font-family: var(--mplus-10-font);
font-size: 1.254rem;
display: flex;
justify-content: space-between;
align-items: center;
a {
flex: 1;
background-color: var(--bg-1);
padding: 6px;
color: var(--border-0);
text-decoration: none;
}
time {
background-color: var(--bg-5);
padding: 6px;
}
&:hover {
a { background-color: var(--bg-7); }
time { background-color: var(--border-6); }
}
}
&:last-child { border: none; }
}
}
hgroup {
margin: 0 4px;
background-color: var(--bg-0);
&:first-child { margin-top: 4px; }
&:last-child {
border-bottom: 2px solid var(--border-2);
margin-bottom: 4px;
}
}
@media screen and (max-width: 76em) {
margin-right: 0;
margin-bottom: -2px;
}
}
article {
letter-spacing: 1px;
border: 2px solid var(--border-0);
border-image: var(--outerBorder) 19 9 38 11 fill / 38px 18px 76px 22px;
background-color: var(--bg-3);
padding: 36px 16px 74px 20px;
.inner {
border: 2px solid var(--border-2);
border-image: var(--innerBorder) 3 2 2 fill / 6px 4px 4px;
margin: 14px 4px 8px;
padding: 4px 2px 2px;
background-color: var(--bg-0);
}
.title {
font: normal 1.5rem var(--mplus-12-font);
background-color: var(--bg-2);
padding: 2px 6px;
}
.desc {
background-color: var(--bg-4);
padding: 4px 6px;
flex: 1;
}
header {
border-bottom: 2px solid var(--bg-6);
h1 {
text-align: center;
margin: 6px 2px;
padding: 2px 0;
background-color: var(--border-6);
}
.info {
display: flex;
align-items: baseline;
gap: 2px;
border-style: solid;
border-width: 2px;
border-color: var(--bg-2) var(--bg-2) var(--bg-1) var(--bg-1);
padding: 2px 4px;
time, .section {
display: flex;
width: 100%;
}
}
hr {
background-color: var(--border-5);
border: none;
height: 2px;
}
}
.content {
position: relative;
background-image: linear-gradient(to right, var(--bg-0) 5px, transparent 2px), linear-gradient(var(--bg-4) 2px, transparent 2px);
background-size: 10px 1lh;
background-position-y: 1.9lh;
margin: 0 1rem 2rem;
padding: 2rem 1rem 0;
line-height: 2;
margin-trim: block;
p { margin-block: 1lh; }
@supports not (margin-trim: block) {
:first-child { margin-block-start: 0; }
:last-child { margin-block-end: 0; }
}
@media screen and (max-width: 950px) {
background-position-y: 0.8rem;
padding: 1rem;
margin: 0.25rem 0;
}
}
aside {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: repeat(4, auto);
border-top: 2px solid var(--border-4);
h2 {
display: grid;
place-content: center;
grid-area: 1 / 1 / -1;
padding-top: -2px;
padding-left: 2px;
height: 100%;
border-top: 2px solid var(--border-1);
border-right: 2px solid var(--border-4);
background-color: var(--bg-7);
}
dl {
display: flex;
align-items: center;
padding: 2px 6px;
border-bottom: 2px solid var(--border-4);
border-top: 2px solid var(--border-1);
border-left: 2px solid var(--border-1);
&:first-of-type > dd {
display: flex;
align-items: center;
gap: 6px;
margin: -2px;
padding: 0 6px;
}
&:last-child { border-bottom: none; }
}
}
}
</style>