Add aesthetic timeline to post lists

This commit is contained in:
2025-11-19 00:54:58 +08:00
parent 10e4e7e21e
commit fe191752da
5 changed files with 26 additions and 5 deletions

View File

@@ -1,5 +1,6 @@
import { getAllPostsSorted } from '@/lib/posts';
import { PostListWithControls } from '@/components/post-list-with-controls';
import { TimelineWrapper } from '@/components/timeline-wrapper';
export const metadata = {
title: '所有文章'

View File

@@ -2,6 +2,7 @@ import Link from 'next/link';
import { getAllPostsSorted } from '@/lib/posts';
import { siteConfig } from '@/lib/config';
import { PostListItem } from '@/components/post-list-item';
import { TimelineWrapper } from '@/components/timeline-wrapper';
export default function HomePage() {
const posts = getAllPostsSorted().slice(0, siteConfig.postsPerPage);
@@ -29,11 +30,11 @@ export default function HomePage() {
</Link>
</div>
<ul className="space-y-3">
<TimelineWrapper>
{posts.map((post) => (
<PostListItem key={post._id} post={post} />
))}
</ul>
</TimelineWrapper>
</div>
</section>
);

View File

@@ -18,7 +18,8 @@ export function PostListItem({ post }: Props) {
post.description || post.custom_excerpt || post.body?.raw?.slice(0, 120);
return (
<li>
<li className="relative pl-6">
<span className="pointer-events-none absolute left-0 top-6 z-10 h-3 w-3 rounded-full border-2 border-white bg-gradient-to-br from-blue-500 via-sky-400 to-indigo-400 shadow-md dark:border-slate-900" aria-hidden="true" />
<article className="motion-card group relative flex gap-4 rounded-lg border border-slate-200/70 bg-white/90 p-4 shadow-sm dark:border-slate-800 dark:bg-slate-900/80">
<div className="pointer-events-none absolute inset-x-0 top-0 h-0.5 origin-left scale-x-0 bg-gradient-to-r from-blue-500 via-sky-400 to-indigo-500 opacity-80 transition-transform duration-300 ease-out group-hover:scale-x-100 dark:from-blue-400 dark:via-sky-300 dark:to-indigo-400" />
{cover && (

View File

@@ -151,11 +151,11 @@ export function PostListWithControls({ posts, pageSize }: Props) {
</div>
) : (
<ul className="space-y-3">
<div className="space-y-3">
{currentPosts.map((post) => (
<PostListItem key={post._id} post={post} />
))}
</ul>
</div>
)}
{totalPages > 1 && currentPosts.length > 0 && (

View File

@@ -0,0 +1,18 @@
import { ReactNode } from 'react';
import clsx from 'clsx';
interface TimelineWrapperProps {
children: ReactNode;
className?: string;
}
export function TimelineWrapper({ children, className }: TimelineWrapperProps) {
return (
<div className={clsx('relative pl-8', className)}>
<div className="pointer-events-none absolute left-3 top-0 h-full w-px bg-gradient-to-b from-transparent via-slate-200 to-transparent dark:via-slate-700" aria-hidden="true" />
<div className="space-y-4">
{children}
</div>
</div>
);
}