Files
writer-work-flow/apps/web/app/loading.tsx
Yaojia Wang 67e30a6863 feat(ui): P3 页面级应用(作品库卡片/空态/加载/设置/次级页)
- 作品库卡片重设计:书脊封面字块 + 衬线书名 + 一句话故事(缺失给占位) +
  元信息行(题材徽章/StatusDot 待审/mono 时间),Card tone=card 浮起消塌陷
- EmptyState 中性化 + inline/card/bare 变体 + eyebrow(向后兼容)
- loading 骨架化(Skeleton 拼作品库结构,motion-safe)
- 设置页拆分 ProvidersSettings 489→198 + 5 个子组件,凭据点用 StatusDot
- 次级页(向导/模板/codex/大纲)排版字阶与圆角 token 收敛
2026-07-11 07:36:32 +02:00

80 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Card } from "@/components/ui/Card";
import { PageContainer } from "@/components/ui/PageContainer";
import { Skeleton } from "@/components/ui/Skeleton";
// 全站加载骨架:与作品库结构近似(标题条 + 工具条 + 卡片网格),
// motion-safe 脉冲,尊重 prefers-reduced-motion。
export default function Loading() {
return (
<main className="min-h-screen bg-bg">
<PageContainer>
<div role="status" aria-label="加载中" className="space-y-8">
<span className="sr-only"></span>
<HeaderSkeleton />
<ToolbarSkeleton />
<GridSkeleton />
</div>
</PageContainer>
</main>
);
}
// 标题区:大标题条 + 说明条 + 右侧两枚按钮位。
function HeaderSkeleton() {
return (
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div className="space-y-3">
<Skeleton className="h-8 w-48" />
<Skeleton className="h-4 w-72 max-w-full" />
</div>
<div className="flex gap-2">
<Skeleton className="h-9 w-28" />
<Skeleton className="h-9 w-24" />
</div>
</div>
);
}
// 工具条:搜索框 + 三枚控件位。
function ToolbarSkeleton() {
return (
<Card flat className="grid gap-3 p-3 md:grid-cols-[1fr_auto_auto_auto]">
<Skeleton className="h-9 w-full" />
<Skeleton className="h-9 w-28" />
<Skeleton className="h-9 w-28" />
<Skeleton className="h-9 w-20" />
</Card>
);
}
// 卡片网格6 张与作品卡等高的占位卡。
function GridSkeleton() {
return (
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<CardSkeleton key={i} />
))}
</div>
);
}
// 单张作品卡骨架:标题 + 徽章 + 三行简介 + 底部时间。
function CardSkeleton() {
return (
<Card flat className="flex h-full min-h-[176px] flex-col p-6">
<div className="mb-4 flex items-start justify-between gap-3">
<div className="min-w-0 flex-1 space-y-3">
<Skeleton className="h-6 w-3/4" />
<Skeleton className="h-5 w-16 rounded-full" />
</div>
<Skeleton className="h-8 w-8 shrink-0" />
</div>
<div className="space-y-2">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-5/6" />
</div>
<Skeleton className="mt-auto h-3 w-28" />
</Card>
);
}