Commit ae299f4

HPCesia <me@hpcesia.com>
2025-02-12 14:04:20
refactor: refactor layouts
1 parent 9794a90
src/components/PostPage.astro → src/components/PostsPage.astro
File renamed without changes
src/components/SideToolBar.astro
@@ -5,7 +5,12 @@ import Button from './widgets/Button.astro';
 import DarkModeButton from './widgets/DarkModeButton.astro';
 ---
 
-<div id="side-toolbar" class="fixed right-0 bottom-10 z-30 grid grid-cols-1 gap-2">
+<div
+  id="side-toolbar"
+  class="fixed right-0 bottom-10 z-30 grid grid-cols-1 gap-2"
+  transition:name="side-toolbar"
+  transition:persist
+>
   <div
     id="stb-hide"
     class="grid translate-x-full grid-cols-1 gap-2 pr-4 duration-500 ease-in-out"
@@ -133,5 +138,6 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
     });
   }
 
-  document.addEventListener('astro:page-load', initSideToolBar);
+  document.addEventListener('astro:after-swap', initSideToolBar);
+  initSideToolBar();
 </script>
src/layouts/GridLayout.astro
@@ -1,27 +0,0 @@
----
-import MainLayout from '@layouts/MainLayout.astro';
-
-interface Props {
-  title?: string;
-  description?: string;
-  lang?: string;
-}
-const { title, description, lang } = Astro.props;
----
-
-<MainLayout title={title} description={description} lang={lang}>
-  <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col gap-4">
-    <slot name="header-content" />
-    <div class="flex gap-4">
-      <div id="main-content" class="my-4 w-full">
-        <slot />
-      </div>
-      <div id="aside-content" class="my-4 flex w-96 flex-col gap-4 max-xl:hidden">
-        <slot name="aside-fixed" />
-        <div class="sticky top-20 flex flex-col gap-4">
-          <slot name="aside-sticky" />
-        </div>
-      </div>
-    </div>
-  </div>
-</MainLayout>
src/layouts/MainLayout.astro
@@ -21,7 +21,20 @@ const { title, description, lang } = Astro.props;
     <slot name="header" />
     <div id="body-wrap" class="w-full items-center md:px-4">
       <!-- Main content -->
-      <slot />
+      <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col gap-4">
+        <slot name="header-content" />
+        <div class="flex gap-4">
+          <main id="main-content" class="my-4 w-full">
+            <slot />
+          </main>
+          <div id="aside-content" class="my-4 flex w-96 flex-col gap-4 max-xl:hidden">
+            <slot name="aside-fixed" />
+            <div class="sticky top-20 flex flex-col gap-4">
+              <slot name="aside-sticky" />
+            </div>
+          </div>
+        </div>
+      </div>
     </div>
   </Navbar>
   {searchConfig.enable && <Search />}
src/layouts/PostPageLayout.astro
@@ -0,0 +1,35 @@
+---
+import { articleConfig, commentConfig } from '@/config';
+import ProfileCard from '@components/aside/ProfileCard.astro';
+import TOC from '@components/aside/TOC.astro';
+import Comment from '@components/Comment.astro';
+import type { MarkdownHeading } from 'astro';
+import MainLayout from './MainLayout.astro';
+
+interface Props {
+  title: string;
+  description?: string;
+  lang?: string;
+  headings?: MarkdownHeading[];
+  comment?: boolean;
+}
+
+const { title, description, lang, headings, comment } = Astro.props;
+---
+
+<MainLayout title={title} description={description} lang={lang}>
+  <slot slot="head" name="head" />
+  <slot slot="header-content" name="header-content" />
+  <div class="card border-base-300 border-2 px-6 py-4">
+    <slot />
+    {comment && commentConfig.enable && <Comment />}
+  </div>
+  <Fragment slot="aside-fixed">
+    <ProfileCard />
+    <slot name="aside-fixed" />
+  </Fragment>
+  <Fragment slot="aside-sticky">
+    {articleConfig.toc && headings && <TOC headings={headings} />}
+    <slot name="aside-sticky" />
+  </Fragment>
+</MainLayout>
src/pages/archives/categories/[category]/[page].astro
@@ -2,9 +2,9 @@
 import { siteConfig } from '@/config';
 import ProfileCard from '@components/aside/ProfileCard.astro';
 import CategoryBar from '@components/misc/CategoryBar.astro';
-import PostPage from '@components/PostPage.astro';
+import PostsPage from '@components/PostsPage.astro';
 import I18nKey from '@i18n/I18nKey';
-import GridLayout from '@layouts/GridLayout.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { getCategories, getSortedPosts } from '@utils/content-utils';
 
 export async function getStaticPaths() {
@@ -36,9 +36,9 @@ const { category } = Astro.params;
 const categories = await getCategories();
 ---
 
-<GridLayout title={category}>
+<MainLayout title={category}>
   <CategoryBar categories={Array.from(categories.keys())} currentCategory={category} />
-  <PostPage
+  <PostsPage
     posts={posts}
     currentPage={currentPage}
     baseUrl={`/archives/categories/${category}`}
@@ -46,4 +46,4 @@ const categories = await getCategories();
   <Fragment slot="aside-fixed">
     <ProfileCard />
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/archives/categories/index.astro
@@ -12,7 +12,7 @@ import Button from '@components/widgets/Button.astro';
 import MetaIcon from '@components/widgets/MetaIcon.astro';
 import I18nKey from '@i18n/I18nKey';
 import { i18n } from '@i18n/translation';
-import GridLayout from '@layouts/GridLayout.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { Icon } from 'astro-icon/components';
 
 const categoriesMap = await getCategories();
@@ -28,7 +28,7 @@ if (uncategorizedPosts.length > 0)
   categoryPosts.set(i18n(I18nKey.uncategorized) as string, uncategorizedPosts);
 ---
 
-<GridLayout title={i18n(I18nKey.categories)}>
+<MainLayout title={i18n(I18nKey.categories)}>
   <div
     class="card card-border border-base-300 mx-auto flex flex-col items-center border-2 px-6 py-4"
   >
@@ -140,4 +140,4 @@ if (uncategorizedPosts.length > 0)
       }))}
     />
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/archives/tags/[tag]/[page].astro
@@ -1,9 +1,9 @@
 ---
 import { siteConfig } from '@/config';
-import PostPage from '@components/PostPage.astro';
+import PostsPage from '@components/PostsPage.astro';
 import ProfileCard from '@components/aside/ProfileCard.astro';
 import I18nKey from '@i18n/I18nKey';
-import GridLayout from '@layouts/GridLayout.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { getSortedPosts } from '@utils/content-utils';
 
 export async function getStaticPaths() {
@@ -35,12 +35,12 @@ const { posts, currentPage } = Astro.props;
 const { tag } = Astro.params;
 ---
 
-<GridLayout title={tag}>
+<MainLayout title={tag}>
   <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center">
     <h1 class="my-8 text-3xl font-bold">{tag}</h1>
   </div>
-  <PostPage posts={posts} currentPage={currentPage} baseUrl={`/archives/tags/${tag}`} />
+  <PostsPage posts={posts} currentPage={currentPage} baseUrl={`/archives/tags/${tag}`} />
   <Fragment slot="aside-fixed">
     <ProfileCard />
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/archives/tags/index.astro
@@ -7,7 +7,7 @@ import Button from '@components/widgets/Button.astro';
 import MetaIcon from '@components/widgets/MetaIcon.astro';
 import I18nKey from '@i18n/I18nKey';
 import { i18n } from '@i18n/translation';
-import GridLayout from '@layouts/GridLayout.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { Icon } from 'astro-icon/components';
 
 const tagsMap = await getTags();
@@ -24,7 +24,7 @@ const untaggedPosts = allPosts
 if (untaggedPosts.length > 0) tagPosts.set(i18n(I18nKey.untagged) as string, untaggedPosts);
 ---
 
-<GridLayout title={i18n(I18nKey.tags)}>
+<MainLayout title={i18n(I18nKey.tags)}>
   <div
     class="card card-border border-base-300 mx-auto flex flex-col items-center border-2 px-6 py-4"
   >
@@ -133,4 +133,4 @@ if (untaggedPosts.length > 0) tagPosts.set(i18n(I18nKey.untagged) as string, unt
       }))}
     />
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/archives/[...time].astro
@@ -7,7 +7,7 @@ import Button from '@components/widgets/Button.astro';
 import MetaIcon from '@components/widgets/MetaIcon.astro';
 import I18nKey from '@i18n/I18nKey';
 import { i18n } from '@i18n/translation';
-import GridLayout from '@layouts/GridLayout.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { getCategoryUrl, getPostsCount, getSortedPosts, getTagUrl } from '@utils/content-utils';
 import { Icon } from 'astro-icon/components';
 
@@ -72,7 +72,7 @@ const slug = Astro.params.time;
 const postCount = await getPostsCount();
 ---
 
-<GridLayout>
+<MainLayout>
   <div class="card border-base-300 mb-4 border-2">
     <div class="breadcrumbs card-body text-md py-3">
       <ul>
@@ -271,4 +271,4 @@ const postCount = await getPostsCount();
       )
     }
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/posts/[article].astro
@@ -1,12 +1,8 @@
 ---
-import { articleConfig, commentConfig } from '@/config';
-import ProfileCard from '@components/aside/ProfileCard.astro';
-import TOC from '@components/aside/TOC.astro';
-import Comment from '@components/Comment.astro';
 import License from '@components/misc/License.astro';
 import PostInfo from '@components/misc/PostInfo.astro';
 import Markdown from '@components/utils/Markdown.astro';
-import GridLayout from '@layouts/GridLayout.astro';
+import PostPageLayout from '@layouts/PostPageLayout.astro';
 import { getOrCreateRenderResult } from '@utils/content-utils';
 import { getCollection } from 'astro:content';
 
@@ -24,7 +20,13 @@ const { Content, headings, remarkPluginFrontmatter } = await getOrCreateRenderRe
 const description = article.data.description || remarkPluginFrontmatter.excerpt;
 ---
 
-<GridLayout title={article.data.title} description={description}>
+<PostPageLayout
+  title={article.data.title}
+  description={description}
+  headings={headings}
+  comment={article.data.comment}
+  lang={article.data.lang}
+>
   <Fragment slot="header-content">
     <PostInfo
       title={article.data.title}
@@ -37,17 +39,8 @@ const description = article.data.description || remarkPluginFrontmatter.excerpt;
       class="mx-2 mt-4"
     />
   </Fragment>
-  <div class="card border-base-300 border-2 px-6 py-4">
-    <Markdown>
-      <Content />
-    </Markdown>
-    <License time={article.data.published} lang={article.data.lang} />
-    {article.data.comment && commentConfig.enable && <Comment />}
-  </div>
-  <Fragment slot="aside-fixed">
-    <ProfileCard />
-  </Fragment>
-  <Fragment slot="aside-sticky">
-    {articleConfig.toc && <TOC headings={headings} />}
-  </Fragment>
-</GridLayout>
+  <Markdown>
+    <Content />
+  </Markdown>
+  <License time={article.data.published} lang={article.data.lang} />
+</PostPageLayout>
src/pages/[...page].astro
@@ -3,8 +3,8 @@ import { siteConfig } from '@/config';
 import ProfileCard from '@components/aside/ProfileCard.astro';
 import SiteInfoCard from '@components/aside/SiteInfoCard.astro';
 import CategoryBar from '@components/misc/CategoryBar.astro';
-import PostPage from '@components/PostPage.astro';
-import GridLayout from '@layouts/GridLayout.astro';
+import PostsPage from '@components/PostsPage.astro';
+import MainLayout from '@layouts/MainLayout.astro';
 import { getCategories, getSortedPosts } from '@utils/content-utils';
 
 export async function getStaticPaths() {
@@ -22,9 +22,9 @@ const articles = await getSortedPosts();
 const categories = await getCategories();
 ---
 
-<GridLayout>
+<MainLayout>
   <CategoryBar categories={Array.from(categories.keys())} />
-  <PostPage
+  <PostsPage
     posts={articles}
     currentPage={page}
     baseUrl={`/page`}
@@ -34,4 +34,4 @@ const categories = await getCategories();
     <ProfileCard />
     <SiteInfoCard />
   </Fragment>
-</GridLayout>
+</MainLayout>
src/pages/about.astro
@@ -1,51 +1,16 @@
 ---
-import { commentConfig, profileConfig } from '@/config';
-import Comment from '@components/Comment.astro';
-import ImageWrapper from '@components/utils/ImageWrapper.astro';
 import Markdown from '@components/utils/Markdown.astro';
-import Button from '@components/widgets/Button.astro';
 import I18nKey from '@i18n/I18nKey';
 import { i18n } from '@i18n/translation';
-import MainLayout from '@layouts/MainLayout.astro';
-import { Icon } from 'astro-icon/components';
+import PostPageLayout from '@layouts/PostPageLayout.astro';
 import { getEntry, render } from 'astro:content';
 
 const aboutMd = await getEntry('spec', 'about');
 const { Content } = aboutMd ? await render(aboutMd) : Fragment;
 ---
 
-<MainLayout title={i18n(I18nKey.about)}>
-  <div class="mx-auto flex max-w-(--breakpoint-xl) flex-col items-center justify-center">
-    <div class="hero my-4 w-5/6 md:w-2/3">
-      <div class="hero-content flex-col-reverse md:flex-row">
-        <div class="mr-auto flex flex-col">
-          <h1>
-            <span class="text-xl">Hi! I'm </span>
-            <span class="text-2xl font-bold">{profileConfig.name}</span>
-          </h1>
-          <div class="mt-2">
-            {profileConfig.bio}
-          </div>
-          <div class="mt-4 flex">
-            {
-              profileConfig.links.map((link) => (
-                <Button href={link.url} title={link.name} class="btn-circle btn-ghost text-2xl">
-                  <Icon name={link.icon} />
-                </Button>
-              ))
-            }
-          </div>
-        </div>
-        <ImageWrapper
-          class="h-0 min-h-48 w-0 min-w-48 rounded-lg shadow-2xl"
-          src={profileConfig.avatar}
-          alt={profileConfig.name}
-        />
-      </div>
-    </div>
-    <Markdown class="w-5/6 md:w-3/4">
-      <Content />
-    </Markdown>
-    {aboutMd?.data.comment && commentConfig.enable && <Comment />}
-  </div>
-</MainLayout>
+<PostPageLayout title={i18n(I18nKey.about) as string} comment={aboutMd?.data.comment}>
+  <Markdown>
+    <Content />
+  </Markdown>
+</PostPageLayout>