Skip to content

Commit a9504d8

Browse files
committed
feat: add loading skeleton for ArticleFeed component
- Introduced `ArticleFeedCardSkeleton` to provide a consistent loading state that mirrors the layout of `ArticleCard`. - Replaced static loading divs with a dynamic map to render multiple skeletons during data fetching.
1 parent fd67175 commit a9504d8

2 files changed

Lines changed: 33 additions & 17 deletions

File tree

src/app/(home)/_components/ArticleFeed.tsx

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,35 @@ import getFileUrl from "@/utils/getFileUrl";
88
import { useInfiniteQuery } from "@tanstack/react-query";
99
import { useState } from "react";
1010

11+
/** Mirrors `ArticleCard` layout so loading state matches width, rhythm, and rough height. */
12+
function ArticleFeedCardSkeleton() {
13+
return (
14+
<div
15+
className="flex animate-pulse flex-col"
16+
aria-hidden
17+
suppressHydrationWarning
18+
>
19+
<div className="mb-4 flex items-center">
20+
<div className="size-8 shrink-0 rounded-full bg-muted" />
21+
<div className="ml-2.5 flex min-w-0 flex-1 flex-col gap-2 py-0.5">
22+
<div className="h-3.5 w-28 max-w-[50%] rounded bg-muted" />
23+
<div className="h-2.5 w-36 max-w-[60%] rounded bg-muted" />
24+
</div>
25+
</div>
26+
<div className="mb-3 flex flex-col space-y-2">
27+
<div className="h-5 w-[85%] max-w-xl rounded bg-muted" />
28+
<div className="h-3.5 w-full rounded bg-muted" />
29+
<div className="h-3.5 w-[92%] rounded bg-muted" />
30+
</div>
31+
<div className="relative mt-4 aspect-video overflow-hidden rounded-md bg-muted" />
32+
<div className="mt-4 flex items-center justify-between">
33+
<div className="h-8 w-28 rounded-md bg-muted" />
34+
<div className="h-8 w-8 rounded-md bg-muted" />
35+
</div>
36+
</div>
37+
);
38+
}
39+
1140
const ArticleFeed = () => {
1241
const [feedType, setFeedType] = useState<"articles" | "series">("articles");
1342

@@ -50,22 +79,9 @@ const ArticleFeed = () => {
5079
<div className="flex flex-col gap-10">
5180
{articleFeedQuery.isPending && (
5281
<>
53-
<div
54-
className="h-56 bg-muted animate-pulse mx-4"
55-
suppressHydrationWarning={true}
56-
/>
57-
<div
58-
className="h-56 bg-muted animate-pulse mx-4"
59-
suppressHydrationWarning={true}
60-
/>
61-
<div
62-
className="h-56 bg-muted animate-pulse mx-4"
63-
suppressHydrationWarning={true}
64-
/>
65-
<div
66-
className="h-56 bg-muted animate-pulse mx-4"
67-
suppressHydrationWarning={true}
68-
/>
82+
{[0, 1, 2, 3].map((i) => (
83+
<ArticleFeedCardSkeleton key={i} />
84+
))}
6985
</>
7086
)}
7187
{/* <pre>{JSON.stringify(articleFeedQuery, null, 2)}</pre> */}

src/components/ArticleCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const ArticleCard = ({
107107

108108
{coverImage && (
109109
<Link href={articleUrl} className="block">
110-
<div className="relative mt-4 overflow-hidden rounded-md aspect-[16/9]">
110+
<div className="relative mt-4 aspect-video overflow-hidden rounded-md">
111111
<Image
112112
src={coverImage}
113113
alt={title}

0 commit comments

Comments
 (0)