From de78d82d7a570133eb436ac8ae2f4382fedfdb32 Mon Sep 17 00:00:00 2001
From: Youwen Wu <youwenw@gmail.com>
Date: Sun, 5 May 2024 21:53:44 -0700
Subject: [PATCH] feat: sticky position toc below header

---
 src/lib/components/Blog/Article.svelte       | 26 ------------------
 src/lib/components/Blog/ArticleHeader.svelte | 29 ++++++++++++++++++++
 src/routes/blog/[...slug]/+page.svelte       | 13 +++++++--
 3 files changed, 39 insertions(+), 29 deletions(-)
 create mode 100644 src/lib/components/Blog/ArticleHeader.svelte

diff --git a/src/lib/components/Blog/Article.svelte b/src/lib/components/Blog/Article.svelte
index 7fd9713..3d8a0ff 100644
--- a/src/lib/components/Blog/Article.svelte
+++ b/src/lib/components/Blog/Article.svelte
@@ -1,34 +1,8 @@
 <script lang="ts">
-  import PostMetadata from './PostMetadata.svelte'
-  import Crumbs from './Crumbs.svelte'
-
   export let doc: BlogDocument
 </script>
 
 <article>
-  <Crumbs slug={doc.slug} title={doc.title} />
-  <header class="space-y-6">
-    <div class="space-y-2">
-      <h1 class="scroll-m-20 text-5xl font-bold font-serif tracking-tight">
-        {doc.title}
-      </h1>
-      <p class="text-balance text-lg text-muted-foreground">
-        {doc.blurb}
-      </p>
-      <PostMetadata
-        primaryTags={doc.primaryTags}
-        secondaryTags={doc.secondaryTags}
-        date={doc.date}
-        length={doc.content.length}
-        reverseDateAndRest
-      />
-    </div>
-    <figure class="w-full lg:w-[80%]">
-      <img src={doc.image.src} alt={doc.image.alt} class="rounded-xl shadow-md" />
-      <figcaption class="mt-2 text-center text-muted-foreground">{doc.image.caption}</figcaption>
-    </figure>
-  </header>
-
   <div class="markdown-body mb-8 font-serif">
     {@html doc.content}
   </div>
diff --git a/src/lib/components/Blog/ArticleHeader.svelte b/src/lib/components/Blog/ArticleHeader.svelte
new file mode 100644
index 0000000..b2a024a
--- /dev/null
+++ b/src/lib/components/Blog/ArticleHeader.svelte
@@ -0,0 +1,29 @@
+<script lang="ts">
+  import PostMetadata from './PostMetadata.svelte'
+  import Crumbs from './Crumbs.svelte'
+
+  export let doc: BlogDocument
+</script>
+
+<Crumbs slug={doc.slug} title={doc.title} />
+<header class="space-y-6">
+  <div class="space-y-2">
+    <h1 class="scroll-m-20 text-5xl font-bold font-serif tracking-tight">
+      {doc.title}
+    </h1>
+    <p class="text-balance text-lg text-muted-foreground">
+      {doc.blurb}
+    </p>
+    <PostMetadata
+      primaryTags={doc.primaryTags}
+      secondaryTags={doc.secondaryTags}
+      date={doc.date}
+      length={doc.content.length}
+      reverseDateAndRest
+    />
+  </div>
+  <figure class="w-full lg:w-[80%]">
+    <img src={doc.image.src} alt={doc.image.alt} class="rounded-xl shadow-md" />
+    <figcaption class="mt-2 text-center text-muted-foreground">{doc.image.caption}</figcaption>
+  </figure>
+</header>
diff --git a/src/routes/blog/[...slug]/+page.svelte b/src/routes/blog/[...slug]/+page.svelte
index fa3371f..dc37a75 100644
--- a/src/routes/blog/[...slug]/+page.svelte
+++ b/src/routes/blog/[...slug]/+page.svelte
@@ -7,6 +7,7 @@
   import '$lib/styles/katex.css'
   import '$lib/styles/markdown.css'
   import '$lib/styles/tokyo-night-dark.min.css'
+  import ArticleHeader from '$lib/components/Blog/ArticleHeader.svelte'
 
   const tocStore = createTocStore()
 
@@ -33,7 +34,13 @@
 
 <TocHeader {tocStore} placeholder="On this page" />
 
-<div class="lg:flex mx-auto mt-24 lg:mt-14 px-4">
+<div class="max-w-3xl 2xl:max-w-3xl px-4 xl:px-0 xl:mx-auto mt-14">
+  <div class="flex-grow basis-3/4 xl:basis-2/4 flex-shrink">
+    <ArticleHeader {doc} />
+  </div>
+</div>
+
+<div class="lg:flex mx-auto px-4">
   <div class="flex-shrink xl:basis-1/4" />
   <main
     class="flex-grow basis-3/4 xl:basis-2/4 flex-shrink"
@@ -51,8 +58,8 @@
     <Article {doc} />
   </main>
 
-  <aside class="basis-1/4 relative hidden lg:block">
-    <div class="fixed mx-8">
+  <aside class="basis-1/4 relative hidden lg:block mt-10">
+    <div class="sticky top-32 mx-8">
       <StickyToc {tocStore} />
     </div>
   </aside>