Commit e0f8a9a

HPCesia <me@hpcesia.com>
2026-08-10 12:41:08
Organize posts list by publish date
1 parent 4249d07
Changed files (2)
src
components
pages
src/components/widgets/PostsList.astro
@@ -0,0 +1,57 @@
+---
+import type { CollectionEntry } from "astro:content";
+
+import { url } from "@/utils/url.ts";
+
+interface Props {
+  posts: CollectionEntry<"posts">[];
+}
+
+const { posts } = Astro.props;
+---
+<nav class="posts-list">
+  <ol>
+    {
+      posts.map((post) => {
+        const dt = Temporal.ZonedDateTime.from(post.data.date).toPlainDateTime();
+        return (
+          <li>
+            <a href={url(`/posts/${post.id}`)}>{post.data.title}</a>
+            <time datetime={dt.toString()}>
+              {dt.toPlainDate().toLocaleString()}
+            </time>
+          </li>
+        );
+      })
+    }
+  </ol>
+</nav>
+
+<style lang="scss" is:inline>
+nav.posts-list ol li {
+  display: grid;
+  align-items: first baseline;
+  grid-template-columns: 1fr auto;
+  gap: 1rem;
+
+  &::before {
+    /* remove ::before */
+    content: initial;
+  }
+
+  a {
+    color: inherit;
+    text-decoration-color: color-mix(in oklab, var(--color-base-content) 60%,
+      transparent);
+
+    &:hover {
+      text-decoration-color: var(--color-base-content);
+    }
+  }
+
+  time {
+    font-size: 0.875rem;
+    color: color-mix(in oklab, var(--color-base-content) 80%, transparent);
+  }
+}
+</style>
src/pages/posts/index.astro
@@ -1,19 +1,35 @@
 ---
 import { getCollection } from "astro:content";
-import { url } from "@/utils/url";
 
 import BaseLayout from "@/layouts/BaseLayout.astro";
+import PostsList from "@/components/widgets/PostsList.astro";
 
 const posts = await getCollection("posts");
+const sortedPosts = posts.sort(
+  (a, b) => Temporal.ZonedDateTime.compare(b.data.date, a.data.date),
+);
+const postsByYear = sortedPosts.reduce(
+  (acc, post) => {
+    const year = Temporal.ZonedDateTime.from(post.data.date).year;
+    if (!acc[year]) {
+      acc[year] = [];
+    }
+    acc[year].push(post);
+    return acc;
+  },
+  {} as Record<number, typeof posts>,
+);
 ---
 <BaseLayout title="Posts">
   <h1>Posts</h1>
   {
-    posts.map((post) => (
-      <li>
-        <a href={url("/posts/" + post.id)}>{post.data.title}</a>
-        <time>{Temporal.ZonedDateTime.from(post.data.date).toPlainDateTime().toLocaleString("en-US")}</time>
-      </li>)
-    )
+    Object.entries(postsByYear)
+      .reverse()
+      .map(([year, posts]) => (
+        <section>
+          <h2>{year}</h2>
+          <PostsList posts={posts} />
+        </section>
+      ))
   }
 </BaseLayout>