Skip to content

Commit

Permalink
feat: add prev/next links at the bottom of blog post (#372)
Browse files Browse the repository at this point in the history
* feat: add prev/next links at the bottom of blog post
* fix: update and rerun scripts in post details page after swap

Resolves #358
  • Loading branch information
satnaing authored Sep 16, 2024
1 parent 08b1676 commit 29eff36
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 15 deletions.
115 changes: 101 additions & 14 deletions src/layouts/PostDetails.astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { SITE } from "@config";
export interface Props {
post: CollectionEntry<"blog">;
posts: CollectionEntry<"blog">[];
}
const { post } = Astro.props;
const { post, posts } = Astro.props;
const {
title,
Expand Down Expand Up @@ -44,6 +45,19 @@ const layoutProps = {
ogImage: ogUrl,
scrollSmooth: true,
};
/* ========== Prev/Next Posts ========== */
const allPosts = posts.map(({ data: { title }, slug }) => ({
slug,
title,
}));
const currentPostIndex = allPosts.findIndex(a => a.slug === post.slug);
const prevPost = currentPostIndex !== 0 ? allPosts[currentPostIndex - 1] : null;
const nextPost =
currentPostIndex !== allPosts.length ? allPosts[currentPostIndex + 1] : null;
---

<Layout {...layoutProps}>
Expand Down Expand Up @@ -94,6 +108,72 @@ const layoutProps = {

<ShareLinks />
</div>

<hr class="my-6 border-dashed" />

<!-- Previous/Next Post Buttons -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
{
prevPost && (
<a
href={`/posts/${prevPost.slug}`}
class="flex w-full gap-1 hover:opacity-75"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left flex-none"
>
<>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M15 6l-6 6l6 6" />
</>
</svg>
<div>
<span>Previous Post</span>
<div class="text-sm text-skin-accent/85">{prevPost.title}</div>
</div>
</a>
)
}
{
nextPost && (
<a
href={`/posts/${nextPost.slug}`}
class="flex w-full justify-end gap-1 text-right hover:opacity-75 sm:col-start-2"
>
<div>
<span>Next Post</span>
<div class="text-sm text-skin-accent/85">{nextPost.title}</div>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right flex-none"
>
<>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M9 6l6 6l-6 6" />
</>
</svg>
</a>
)
}
</div>
</main>
<Footer />
</Layout>
Expand All @@ -107,7 +187,7 @@ const layoutProps = {
}
</style>

<script is:inline>
<script is:inline data-astro-rerun>
/** Create a progress indicator
* at the top */
function createProgressBar() {
Expand All @@ -132,20 +212,22 @@ const layoutProps = {
/** Update the progress bar
* when user scrolls */
function updateScrollProgress() {
const winScroll =
document.body.scrollTop || document.documentElement.scrollTop;
const height =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
if (document) {
const myBar = document.getElementById("myBar");
if (myBar) {
myBar.style.width = scrolled + "%";
document.addEventListener("scroll", () => {
const winScroll =
document.body.scrollTop || document.documentElement.scrollTop;
const height =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
if (document) {
const myBar = document.getElementById("myBar");
if (myBar) {
myBar.style.width = scrolled + "%";
}
}
}
});
}
document.addEventListener("scroll", updateScrollProgress);
updateScrollProgress();

/** Attaches links to headings in the document,
* allowing sharing of sections easily */
Expand Down Expand Up @@ -220,4 +302,9 @@ const layoutProps = {
});
}
backToTop();

/* Go to page start after page swap */
document.addEventListener("astro:after-swap", () =>
window.scrollTo({ left: 0, top: 0, behavior: "instant" })
);
</script>
6 changes: 5 additions & 1 deletion src/pages/posts/[slug]/index.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
import { type CollectionEntry, getCollection } from "astro:content";
import PostDetails from "@layouts/PostDetails.astro";
import getSortedPosts from "@utils/getSortedPosts";
export interface Props {
post: CollectionEntry<"blog">;
Expand All @@ -18,6 +19,9 @@ export async function getStaticPaths() {
}
const { post } = Astro.props;
const posts = await getCollection("blog");
const sortedPosts = getSortedPosts(posts);
---

<PostDetails post={post} />
<PostDetails post={post} posts={sortedPosts} />

0 comments on commit 29eff36

Please sign in to comment.