Personal Site
1---
2import { getCollection } from "astro:content";
3
4import BoxTlbr from "/assets/box-tlbr.png";
5import Hr from "/assets/hr.png";
6import Box4x3Mask from "/assets/box-4x3-mask.png";
7
8const posts = await getCollection("blog").then((x) =>
9 x.sort(
10 (a, b) =>
11 // cast needed as you can subtract Date but ts doesnt like it
12 (b.data.pub as unknown as number) - (a.data.pub as unknown as number),
13 ),
14);
15
16interface Props {
17 heading?: string;
18}
19
20const HeadingLevel = Astro.props.heading ?? "h2";
21---
22
23<section
24 class="blog"
25 style={`
26 --box-tlbr-png: url(${BoxTlbr.src});
27 --hr-png: url(${Hr.src});
28 --box-4x3-mask-png: url(${Box4x3Mask.src})
29`}
30>
31 <HeadingLevel>Blog Posts</HeadingLevel>
32 {
33 posts.map((post) => (
34 <article class="post">
35 <a href={`/blog/${post.id}`}>
36 {import(
37 `../../content/blog/assets/${post.data.banner.replace(".png", "")}.png`
38 ).then(({ default: img }) => (
39 <img src={img.src} alt="" />
40 ))}
41 <hr />
42 <h3 class="title">{post.data.title}</h3>
43 <div class="bio">{post.data.bio}</div>
44 <time
45 datetime={`${post.data.pub.getFullYear()}-${post.data.pub.getMonth()}-${post.data.pub.getDate()}`}
46 class="pub"
47 >
48 {post.data.pub.getDate()}-{post.data.pub.getMonth()}-
49 {post.data.pub.getFullYear()}
50 </time>
51 </a>
52 </article>
53 ))
54 }
55</section>
56
57<style>
58 .blog {
59 contain: size;
60 height: 100%;
61 overflow-y: auto;
62 }
63
64 .post {
65 border-image: var(--box-tlbr-png) 10 10 fill / 20px 20px round;
66 padding: 30px;
67 }
68
69 img {
70 width: 100%;
71 aspect-ratio: 4/3;
72 object-fit: cover;
73 mask-image: var(--box-4x3-mask-png);
74 mask-size: 100%;
75 }
76
77 a {
78 color: black;
79 text-decoration-line: none;
80
81 &:hover,
82 &:focus,
83 &:active {
84 text-decoration-line: underline;
85 }
86
87 &:active {
88 text-decoration-style: dashed;
89 }
90 }
91
92 hr {
93 margin-block: 5px;
94 height: 5px;
95 border: none;
96 border-image: var(--hr-png) 0 5 fill / 0 5px round;
97 }
98</style>