i can't stop obsessing over the blog layout smdh
BIN
public/fonts/dotum-Regular.woff2
Normal file
BIN
public/fonts/dotumche-Regular.woff2
Normal file
BIN
src/assets/buttons.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 254 B |
Before Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 255 B |
@ -10,8 +10,7 @@
|
||||
--sans-font: "Super Star", 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
|
||||
--arial-font: "Arial Pixel", Arial, Helvetica, sans-serif;
|
||||
--pmd-font: "Wonder Mail", Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif;
|
||||
--mplus-10-font: "PixelMPlus 10", "MS Gothic", system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, system-ui-ko, sans-serif;
|
||||
--mplus-12-font: "PixelMPlus 12", "MS Gothic", system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, system-ui-ko, sans-serif;
|
||||
--dotum-font: "DotumChe", "Dotum", system-ui-ko, system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, monospace, sans-serif;
|
||||
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
--bg-color: #e6f2ef;
|
||||
|
@ -2,12 +2,14 @@
|
||||
font-family: "Arial Pixel";
|
||||
src: url("/fonts/pixearg.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Arial Pixel";
|
||||
src: url("/fonts/pixeab.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
font-display: fallback;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@ -16,6 +18,18 @@
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Dotum";
|
||||
src: url("/fonts/dotum-Regular.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "DotumChe";
|
||||
src: url("/fonts/dotumche-Regular.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Kiwi Soda";
|
||||
src: url("/fonts/KiwiSoda.woff2") format("woff2");
|
||||
|
@ -26,10 +26,17 @@ const { title, date, currently } = Astro.props;
|
||||
|
||||
const blog = await getCollection("blog");
|
||||
blog.length = Math.min(blog.length, 12);
|
||||
blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
blog.sort((a, b) => b.data.pubDate!.valueOf() - a.data.pubDate!.valueOf());
|
||||
---
|
||||
<Layout {title}>
|
||||
<slot slot="head" name="head" />
|
||||
<Fragment slot="head">
|
||||
<link rel="preload" href={outerBBS.src} as="image" />
|
||||
<link rel="preload" href={innerBBS.src} as="image" />
|
||||
<link rel="preload" href={sideBBS.src} as="image" />
|
||||
<link rel="preload" href="/fonts/pixearg.woff2" as="font" />
|
||||
<link rel="preload" href="/fonts/pixeab.woff2" as="font" />
|
||||
<slot name="head" />
|
||||
</Fragment>
|
||||
<Navbar />
|
||||
|
||||
<main>
|
||||
@ -143,15 +150,19 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
--border-4: #88aabb;
|
||||
--border-5: #99bbcc;
|
||||
--border-6: #bbccdd;
|
||||
--normal-color: #335577;
|
||||
--active-color: #aa0033;
|
||||
--active-border: #442266;
|
||||
color: #000;
|
||||
}
|
||||
h1 { font: bold 1rem var(--arial-font); }
|
||||
h2 {
|
||||
font: normal 1.5rem var(--mplus-12-font);
|
||||
font: normal 1rem var(--dotum-font);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
main {
|
||||
font: 1rem var(--arial-font);
|
||||
letter-spacing: 1px;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(auto, 75ch);
|
||||
justify-content: center;
|
||||
@ -211,8 +222,7 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
font-family: var(--mplus-10-font);
|
||||
font-size: 1.25rem; /* this should be 20px */
|
||||
font: bold 1em var(--dotum-font);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@ -225,6 +235,17 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
~ .link {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
/* max-width: 19ch; */
|
||||
|
||||
@media screen and (max-width: 76em) {
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +290,6 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
|
||||
article {
|
||||
display: flex;
|
||||
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);
|
||||
@ -286,7 +306,9 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
}
|
||||
|
||||
.title {
|
||||
font: normal 1.5rem var(--mplus-12-font);
|
||||
display: grid;
|
||||
place-content: center;
|
||||
font: normal 1.25em var(--dotum-font);
|
||||
background-color: var(--bg-2);
|
||||
padding: 2px 6px;
|
||||
}
|
||||
@ -316,9 +338,10 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
border-color: var(--bg-2) var(--bg-2) var(--bg-1) var(--bg-1);
|
||||
padding: 2px 4px;
|
||||
|
||||
time, .section {
|
||||
time {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,6 +368,19 @@ blog.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf());
|
||||
|
||||
p { margin-block: 1lh; }
|
||||
a, del, s { text-decoration-thickness: 2px; }
|
||||
a {
|
||||
color: var(--normal-color);
|
||||
|
||||
&:visited {
|
||||
color: var(--active-border);
|
||||
}
|
||||
&:hover {
|
||||
color: var(--active-color);
|
||||
}
|
||||
&:active, &:focus {
|
||||
color: var(--normal-color);
|
||||
}
|
||||
}
|
||||
|
||||
@supports not (margin-trim: block) {
|
||||
:first-child { margin-block-start: 0; }
|
||||
|
@ -2,13 +2,7 @@
|
||||
import Blog from '@/layouts/Blog.astro';
|
||||
import type { GetStaticPaths } from 'astro';
|
||||
import { getCollection, render } from 'astro:content';
|
||||
|
||||
import leftNormal from "$/left-normal.png";
|
||||
import leftHover from "$/left-hover.png";
|
||||
import leftActive from "$/left-active.png";
|
||||
import rightNormal from "$/right-normal.png";
|
||||
import rightHover from "$/right-hover.png";
|
||||
import rightActive from "$/right-active.png";
|
||||
import buttons from "$/buttons.png";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const blog = await getCollection("blog");
|
||||
@ -30,30 +24,37 @@ const next = current === 0 ? undefined : blog[current - 1];
|
||||
<Blog title={entry.data.title!} date={entry.data.pubDate!} currently={entry.data.currently}>
|
||||
<Fragment slot="head">
|
||||
<meta name="description" content={entry.body?.substring(0, 150) + "…"}>
|
||||
<link rel="preload" href={buttons.src} as="image" />
|
||||
</Fragment>
|
||||
|
||||
<Content />
|
||||
|
||||
{(previous || next) && (
|
||||
<div id="blog-pagination" slot="pagination">
|
||||
<footer id="blog-pagination" slot="pagination">
|
||||
{previous && (
|
||||
<a id="previous" aria-label="previous post" href={`/blog/${previous.id}`}>
|
||||
<img class="arrow" src={leftNormal.src} alt="" />
|
||||
{previous.data.title}
|
||||
<a id="previous" aria-label="go to previous post" href={`/blog/${previous.id}`}>
|
||||
<div class="arrow" />
|
||||
<div class="title">
|
||||
<span>{previous.data.title}</span>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{next && (
|
||||
<a id="next" aria-label="next post" href={`/blog/${next.id}`}>
|
||||
{next.data.title}
|
||||
<img class="arrow" src={rightNormal.src} alt="" />
|
||||
<a id="next" aria-label="go to next post" href={`/blog/${next.id}`}>
|
||||
<div class="title">
|
||||
<span>{next.data.title}</span>
|
||||
</div>
|
||||
<div class="arrow" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</footer>
|
||||
)}
|
||||
</Blog>
|
||||
|
||||
<style define:vars={{ leftNormal: `url(${leftNormal.src})`, leftHover: `url(${leftHover.src})`, leftActive: `url(${leftActive.src})`, rightNormal: `url(${rightNormal.src})`, rightHover: `url(${rightHover.src})`, rightActive: `url(${rightActive.src})` }}>
|
||||
<style define:vars={{ buttons: `url(${buttons.src})` }}>
|
||||
#blog-pagination {
|
||||
margin: 1rem 0;
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
@ -61,33 +62,87 @@ const next = current === 0 ? undefined : blog[current - 1];
|
||||
.arrow {
|
||||
width: 36px;
|
||||
height: 50px;
|
||||
background: var(--buttons) no-repeat top left;
|
||||
}
|
||||
|
||||
#previous {
|
||||
grid-column: 1 / 2;
|
||||
justify-self: left;
|
||||
|
||||
.arrow { content: var(--leftNormal) var(--leftHover) var(--leftActive); }
|
||||
&:hover .arrow { content: var(--leftHover); }
|
||||
&:active .arrow, &:focus .arrow { content: var(--leftActive); }
|
||||
.arrow { background-position: 0 0; }
|
||||
&:hover .arrow { background-position: -36px 0; }
|
||||
&:active .arrow, &:focus .arrow { background-position: -72px 0; }
|
||||
|
||||
.title {
|
||||
border-left: none;
|
||||
margin-left: -2px;
|
||||
padding-left: calc(0.5em + 2px);
|
||||
}
|
||||
}
|
||||
|
||||
#next {
|
||||
grid-column: 2 / -1;
|
||||
justify-self: right;
|
||||
|
||||
.arrow { content: var(--rightNormal) var(--rightHover) var(--rightActive); }
|
||||
&:hover .arrow { content: var(--rightHover); }
|
||||
&:active .arrow, &:focus .arrow { content: var(--rightActive); }
|
||||
.arrow { background-position: -108px 0; }
|
||||
&:hover .arrow { background-position: -144px 0; }
|
||||
&:active .arrow, &:focus .arrow { background-position: -180px 0; }
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
border-right: none;
|
||||
margin-right: -2px;
|
||||
padding-right: calc(0.5em + 2px);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
color: var(--bg-0);
|
||||
align-items: stretch;
|
||||
font: bold larger var(--dotum-font);
|
||||
color: var(--normal-color);
|
||||
text-decoration: none;
|
||||
|
||||
.title {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
padding: 0 0.5em;
|
||||
background-color: var(--bg-7);
|
||||
border: 2px solid var(--border-1);
|
||||
box-shadow:
|
||||
inset 2px 2px 0 0 var(--bg-0),
|
||||
inset 4px 4px 0 0 var(--bg-5),
|
||||
inset -2px -2px 0 0 var(--border-5),
|
||||
inset -4px -4px 0 0 var(--border-6);
|
||||
|
||||
@media screen and (468px > width) {
|
||||
> span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc(12ch + 1em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--active-color);
|
||||
.title { border-color: var(--active-border); }
|
||||
}
|
||||
|
||||
&:active, &:focus {
|
||||
color: var(--normal-color);
|
||||
.title {
|
||||
border-color: var(--border-1);
|
||||
box-shadow:
|
||||
inset -2px -2px 0 0 var(--bg-0),
|
||||
inset -4px -4px 0 0 var(--bg-5),
|
||||
inset 2px 2px 0 0 var(--border-5),
|
||||
inset 4px 4px 0 0 var(--border-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,16 +1,14 @@
|
||||
---
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
import { getCollection } from "astro:content";
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
|
||||
const blog = await getCollection("blog");
|
||||
const sorted = Object.groupBy(blog, ({ data }) => data.pubDate!.getMonth());
|
||||
|
||||
dayjs.extend(utc);
|
||||
const getMonth = (id: number) => {
|
||||
function getMonth(id: number): string {
|
||||
let date = new Date();
|
||||
date.setDate(1);
|
||||
date.setMonth(id);
|
||||
return dayjs(date).format("MMMM");
|
||||
}
|
||||
@ -27,8 +25,8 @@ const getMonth = (id: number) => {
|
||||
<ul>
|
||||
{entry[1]?.sort((a, b) => a.data.pubDate!.valueOf() - b.data.pubDate!.valueOf()).map(post => (
|
||||
<li>
|
||||
<time datetime={dayjs(post.data.pubDate).utc(true).toISOString()}>
|
||||
{dayjs(post.data.pubDate).utc(true).format("MMMM DD, YYYY")}
|
||||
<time datetime={formatDate(post.data.pubDate!, true)}>
|
||||
{formatDate(post.data.pubDate!)}
|
||||
</time>
|
||||
<a href={`/blog/${post.id}`}>{post.data.title}</a>
|
||||
</li>
|
||||
|