mirror of
https://github.com/ClovertaTheTrilobita/SanYeCao-blog.git
synced 2026-04-02 01:54:50 +00:00
feat(timeline): added timeline page
fix tags page style
This commit is contained in:
parent
a0c13634f9
commit
b10f60754a
19 changed files with 305 additions and 20 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -9,8 +9,6 @@ image:
|
|||
tags: ["astro", "blogging", "learning in public", "Hello"]
|
||||
---
|
||||
|
||||
Published on: 2022-07-01
|
||||
|
||||
Welcome to my _new blog_ about learning Astro! Here, I will share my learning journey as I build a new website.
|
||||
|
||||
## What I've accomplished
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ author: 'Astro Learner'
|
|||
image:
|
||||
url: 'https://docs.astro.build/assets/rose.webp'
|
||||
alt: 'The Astro logo on a dark background with a pink glow.'
|
||||
tags: ["astro", "blogging", "learning in public", "Hello"]
|
||||
tags: ["astro", "blogging", "learning in public"]
|
||||
---
|
||||
|
||||
Published on: 2022-07-01
|
||||
|
||||
Welcome to my _new blog_ about learning Astro! Here, I will share my learning journey as I build a new website.
|
||||
|
||||
## What I've accomplished
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const t = getTranslations(lang);
|
|||
<a href={`/${lang}`}>{t.nav.home}</a>
|
||||
<a href={`/${lang}/about`}>{t.nav.about}</a>
|
||||
<a href={`/${lang}/tags`}>{t.nav.tags}</a>
|
||||
<a href={`/${lang}/timeline`}>{t.nav.timeline}</a>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const data = Astro.props;
|
|||
<a href={data.url} class="post-link">
|
||||
<div class="post-text">
|
||||
<span class="post-title">{data.title}</span>
|
||||
<span class="post-description">{data.description}</span>
|
||||
<span class="post-date">{data.date}</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -70,6 +71,16 @@ const data = Astro.props;
|
|||
display: block;
|
||||
}
|
||||
|
||||
.post-description {
|
||||
color: black;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
:global(.dark) .post-description {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.post-link {
|
||||
gap: 0.75rem;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const allPosts = await getCollection("blog");
|
|||
<PostItem
|
||||
url={`/${lang}/posts/${post.id}/`}
|
||||
title={post.data.title}
|
||||
description={post.data.description}
|
||||
date={formattedDate}
|
||||
img={post.data.image.url}
|
||||
/>
|
||||
|
|
|
|||
182
src/components/Posts/PostTimeline.astro
Normal file
182
src/components/Posts/PostTimeline.astro
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { getLangFromUrl, getTranslations } from "@/i18n";
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = getTranslations(lang);
|
||||
const allPosts = await getCollection("blog");
|
||||
|
||||
const sortedPosts = [...allPosts].sort(
|
||||
(a, b) =>
|
||||
new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime(),
|
||||
);
|
||||
|
||||
const groupedPosts = sortedPosts.reduce((acc: any[], post: any) => {
|
||||
const month = new Date(post.data.pubDate).toISOString().slice(0, 7);
|
||||
const lastGroup = acc[acc.length - 1];
|
||||
|
||||
if (lastGroup && lastGroup.month === month) {
|
||||
lastGroup.posts.push(post);
|
||||
} else {
|
||||
acc.push({
|
||||
month,
|
||||
posts: [post],
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
---
|
||||
|
||||
<ul class="timeline">
|
||||
{
|
||||
groupedPosts.map((group) => (
|
||||
<li class="timeline-item">
|
||||
<div class="timeline-node" aria-hidden="true" />
|
||||
|
||||
<div class="timeline-group">
|
||||
<p class="post-date">{group.month}</p>
|
||||
|
||||
<div class="month-posts">
|
||||
{group.posts.map((post: any) => (
|
||||
<a
|
||||
href={`/${lang}/posts/${post.id}/`}
|
||||
class="timeline-card"
|
||||
>
|
||||
<h2 class="post-title">{post.data.title}</h2>
|
||||
<p class="post-description">
|
||||
{post.data.description}
|
||||
</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
.timeline {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 1.6rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
bottom: 0.2rem;
|
||||
left: 0.4rem;
|
||||
width: 2px;
|
||||
background: #9aa7b3;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
margin: 0 0 1.8rem 0;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
.timeline-node {
|
||||
position: absolute;
|
||||
left: calc(0.4rem - 0.25rem + 1px);
|
||||
top: 0.75rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background: #8e8e8e;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.timeline-group {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.post-date {
|
||||
margin: 0 0 0.6rem 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
color: #6f8090;
|
||||
}
|
||||
|
||||
.month-posts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.timeline-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
margin: 0;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.5;
|
||||
color: inherit;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.post-description {
|
||||
margin: 0;
|
||||
font-size: 0.88rem;
|
||||
color: #555;
|
||||
font-style: italic;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.timeline-card:hover .post-title {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline::before {
|
||||
background: #6f8090;
|
||||
}
|
||||
|
||||
:global(.dark) .timeline-node {
|
||||
background: #9a9a9a;
|
||||
}
|
||||
|
||||
:global(.dark) .post-date {
|
||||
color: #aab7c4;
|
||||
}
|
||||
|
||||
:global(.dark) .post-description {
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.timeline {
|
||||
padding-left: 1.3rem;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.post-date {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.post-description {
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -8,6 +8,7 @@ export default {
|
|||
posts: "Posts",
|
||||
tags: "Tags",
|
||||
about: "About",
|
||||
timeline: "timeline",
|
||||
},
|
||||
post: {
|
||||
writtenBy: "Written by",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export default {
|
|||
posts: "文章",
|
||||
tags: "标签",
|
||||
about: "关于",
|
||||
timeline: "时间轴"
|
||||
},
|
||||
post: {
|
||||
writtenBy: "作者",
|
||||
|
|
@ -46,7 +47,7 @@ export default {
|
|||
},
|
||||
tags: {
|
||||
title: "标签",
|
||||
description: "在这里收集着整篇博客出现过的标签,点击标签跳转对应的文章列表。"
|
||||
description: "在这里收集着整篇博客出现过的标签,点击标签跳转对应的文章列表。",
|
||||
},
|
||||
footer: {
|
||||
githubIntro: '在 <a href="https://www.github.com/ClovertaTheTrilobita">GitHub</a> 查看更多!',
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const { pageTitle } = Astro.props;
|
|||
|
||||
::view-transition-old(page),
|
||||
::view-transition-new(page) {
|
||||
animation-duration: 0.35s;
|
||||
animation-duration: 0.05s;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ const t = getTranslations(lang);
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div class="post-divider"></div>
|
||||
|
||||
<slot />
|
||||
|
||||
<Giscus />
|
||||
|
|
@ -91,6 +93,15 @@ const t = getTranslations(lang);
|
|||
display: block;
|
||||
}
|
||||
|
||||
.post-divider {
|
||||
border-top: 1px dashed #dfe4e9;
|
||||
margin: 1.2rem 0 1.5rem;
|
||||
}
|
||||
|
||||
:global(.dark) .post-divider {
|
||||
border-top-color: #7f91a3;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { getCollection } from "astro:content";
|
|||
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||
import PostItem from "@/components/Posts/PostItem.astro";
|
||||
import { getTranslations, type Lang } from "@/i18n";
|
||||
import "@/styles/global.css";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await getCollection("blog");
|
||||
|
|
@ -31,10 +32,55 @@ const t = getTranslations(lang);
|
|||
---
|
||||
|
||||
<BaseLayout pageTitle={String(tag)}>
|
||||
<p>
|
||||
{lang === "zh" ? `带有标签 ${tag} 的文章` : `Posts tagged with ${tag}`}
|
||||
<p class="tag-heading">
|
||||
{lang === "zh" ? "带有标签" : "Posts tagged with"}{" "}
|
||||
<span class="tag-chip">{tag}</span>
|
||||
{lang === "zh" ? "的文章" : ""}
|
||||
</p>
|
||||
<ul>
|
||||
{posts.map((post) => <PostItem post={post} lang={lang} />)}
|
||||
{
|
||||
posts.map((post: any) => {
|
||||
const formattedDate = new Date(post.data.pubDate)
|
||||
.toISOString()
|
||||
.split("T")[0];
|
||||
|
||||
return (
|
||||
<PostItem
|
||||
url={`/${lang}/posts/${post.id}/`}
|
||||
title={post.data.title}
|
||||
date={formattedDate}
|
||||
img={post.data.image.url}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.tag-heading {
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
|
||||
.tag-chip {
|
||||
display: inline-block;
|
||||
padding: 0.22em 0.65em;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.2;
|
||||
border: 1px dashed #8b6b4a;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
color: #6f4e37;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
:global(.dark) .tag-chip {
|
||||
border-color: #d8c7a1;
|
||||
color: #e6d8b8;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ const pageTitle = lang === "zh" ? "标签索引" : "Tag Index";
|
|||
<BaseLayout pageTitle={pageTitle}>
|
||||
<h1>{t.tags.title}</h1>
|
||||
<p>{t.tags.description}</p>
|
||||
|
||||
<div class="tags">
|
||||
{
|
||||
tags.map((tag) => (
|
||||
|
|
@ -30,21 +31,37 @@ const pageTitle = lang === "zh" ? "标签索引" : "Tag Index";
|
|||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
a {
|
||||
color: #00539f;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
margin-top: 0.8rem;
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin: 0.25em;
|
||||
border: dotted 1px #a1a1a1;
|
||||
border-radius: 0.5em;
|
||||
padding: 0.5em 1em;
|
||||
font-size: 1.15em;
|
||||
background-color: #f8fcfd;
|
||||
margin: 0;
|
||||
padding: 0.22em 0.65em;
|
||||
font-size: 1rem;
|
||||
line-height: 1.2;
|
||||
border: 1px dashed #8b6b4a;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tag a {
|
||||
color: #6f4e37;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tag a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
:global(.dark) .tag {
|
||||
border-color: #d8c7a1;
|
||||
}
|
||||
|
||||
:global(.dark) .tag a {
|
||||
color: #e6d8b8;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
18
src/pages/[lang]/timeline.astro
Normal file
18
src/pages/[lang]/timeline.astro
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||
import PostTimeline from "@/components/Posts/PostTimeline.astro";
|
||||
import { getLangFromUrl, getTranslations } from "@/i18n";
|
||||
import "@/styles/global.css";
|
||||
|
||||
export function getStaticPaths() {
|
||||
return [{ params: { lang: "zh" } }, { params: { lang: "en" } }];
|
||||
}
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = getTranslations(lang);
|
||||
const headerTitle = lang === "zh" ? "时间轴" : "Timeline";
|
||||
---
|
||||
|
||||
<BaseLayout pageTitle={headerTitle}>
|
||||
<PostTimeline />
|
||||
</BaseLayout>
|
||||
Loading…
Reference in a new issue