Spaces:
Sleeping
Sleeping
| import { | |
| Skeleton, | |
| SkeletonTable, | |
| SkeletonText, | |
| } from "@/components/ui/LoadingSkeleton"; | |
| /* Route-level loading state for /compare — mirrors the page's structure | |
| (heading + dataset chips, Pareto canvas, head-to-head card, efficiency | |
| canvas) so content streams in without layout shift. Server-safe: all | |
| shimmer comes from the .skeleton class, which collapses to a static | |
| block under prefers-reduced-motion. */ | |
| function HeadingSkeleton({ titleWidth = 320 }: { titleWidth?: number }) { | |
| return ( | |
| <div className="hairline-b flex flex-col gap-3 pb-6"> | |
| <Skeleton className="h-3" width={130} /> | |
| <Skeleton className="h-9" width={titleWidth} /> | |
| <SkeletonText className="max-w-2xl" lines={2} lastLineWidth="45%" /> | |
| </div> | |
| ); | |
| } | |
| function ChartCardSkeleton({ height }: { height: number }) { | |
| return ( | |
| <div className="glass depth-2 rounded-sm p-5"> | |
| {/* control row: legend chips left, toggle right */} | |
| <div className="flex flex-wrap items-center justify-between gap-3"> | |
| <div className="flex flex-wrap items-center gap-4"> | |
| {[72, 96, 64, 88].map((w, i) => ( | |
| <Skeleton key={i} className="h-3" width={w} /> | |
| ))} | |
| </div> | |
| <Skeleton className="h-7" width={140} /> | |
| </div> | |
| {/* chart canvas */} | |
| <Skeleton className="mt-4 w-full" height={height} /> | |
| {/* caption */} | |
| <div className="hairline-t mt-4 pt-3"> | |
| <Skeleton className="h-3.5" width="70%" /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| export default function CompareLoading() { | |
| return ( | |
| <div | |
| aria-busy="true" | |
| aria-label="Loading model comparison" | |
| className="flex flex-col gap-12 md:gap-16" | |
| > | |
| {/* 02 · Compare heading + dataset-scope chips */} | |
| <div className="flex flex-col gap-5"> | |
| <HeadingSkeleton titleWidth={340} /> | |
| <div className="flex flex-wrap items-center gap-2"> | |
| <Skeleton className="h-3" width={96} /> | |
| {[88, 76, 112].map((w, i) => ( | |
| <Skeleton key={i} className="h-6 rounded-sm" width={w} /> | |
| ))} | |
| </div> | |
| </div> | |
| {/* pulse line strip */} | |
| <Skeleton className="h-6 w-full" /> | |
| {/* Pareto frontier card */} | |
| <ChartCardSkeleton height={440} /> | |
| {/* 02.1 · Head-to-head */} | |
| <HeadingSkeleton titleWidth={300} /> | |
| <div className="glass depth-2 rounded-sm p-5"> | |
| {/* three model selectors */} | |
| <div className="flex flex-wrap items-end gap-4"> | |
| {[0, 1, 2].map((i) => ( | |
| <div key={i} className="flex min-w-52 flex-1 flex-col gap-1.5"> | |
| <Skeleton className="h-3" width="45%" /> | |
| <Skeleton className="h-9 w-full" /> | |
| </div> | |
| ))} | |
| </div> | |
| {/* delta table */} | |
| <SkeletonTable className="mt-5" rows={6} columns={4} /> | |
| {/* profile bars */} | |
| <div className="mt-5 grid gap-x-10 gap-y-5 sm:grid-cols-2"> | |
| {[0, 1, 2, 3].map((i) => ( | |
| <div key={i} className="flex flex-col gap-2"> | |
| <Skeleton className="h-3" width="35%" /> | |
| <Skeleton className="h-1.5 w-full" /> | |
| <Skeleton className="h-1.5 w-4/5" /> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| {/* 02.2 · Efficiency */} | |
| <HeadingSkeleton titleWidth={360} /> | |
| <ChartCardSkeleton height={360} /> | |
| </div> | |
| ); | |
| } | |