loading.tsx28 lines · main
1/**
2 * Cockpit-wide loading fallback. Shown while an admin page's server-side
3 * /v1/admin/* fetch is in flight, so the operator sees a calm, honest
4 * "working" state instead of a blank frame. Server-safe (no client hooks).
5 *
6 * Deliberately generic — a heading shimmer plus a small grid of card
7 * skeletons — because it backs every cockpit page (overview, billing,
8 * health, mcp), each of which leads with a header and a card row.
9 */
10export default function AdminCockpitLoading() {
11 return (
12 <div className="flex flex-col gap-8" aria-busy="true" aria-live="polite">
13 <span className="sr-only">loading…</span>
14 <header className="flex flex-col gap-2">
15 <div className="h-6 w-48 animate-pulse rounded-[var(--radius-md)] bg-[var(--color-surface)]" />
16 <div className="h-4 w-full max-w-prose animate-pulse rounded-[var(--radius-md)] bg-[var(--color-surface)]" />
17 </header>
18 <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
19 {Array.from({ length: 4 }).map((_, i) => (
20 <div
21 key={i}
22 className="h-24 animate-pulse rounded-[var(--radius-md)] border border-[var(--color-border-subtle)] bg-[var(--color-surface)]"
23 />
24 ))}
25 </div>
26 </div>
27 );
28}