Files
accounted/app/(dashboard)/articles/loading.tsx
T
41424a1650 feat(ux): one silhouette from route fallback to detail content (#1944)
Opening a row on the customers, invoices, verifikat, supplier-invoice,
supplier, article and salary-run lists flashed three unrelated layouts:
the segment's list-shaped loading.tsx (or, for suppliers and articles, the
Hem-shaped dashboard fallback) during the RSC round trip, then the client
page's bare centred spinner in an h-64 box while it fetched, then the
content with a full layout change. Two flashes per click on the most
travelled drill-down path.

- components/common/DetailPageSkeleton.tsx: back link + title row + card
  grid + line block, the silhouette of a document/register detail page;
  InvoiceEditorSkeleton for the editor routes (same shape the Ny faktura
  dialog shows while its chunk loads).
- loading.tsx for every [id] segment (customers, invoices, invoices/edit,
  invoices/credit, bookkeeping, supplier-invoices, suppliers, articles,
  salary/runs) and for the two list segments that had none (suppliers,
  articles, cloned from customers/loading.tsx).
- The client pages render the same skeleton while they fetch instead of
  the centred Loader2, so the RSC fallback to client fallback handoff is
  invisible. The reference-data gates are already gone (A1 to A6); this
  only covers the primary-entity fetch.
- app/(dashboard)/__tests__/detail-loading-states.test.ts pins both.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 15:02:26 +02:00

40 lines
1.3 KiB
TypeScript

import { Skeleton } from '@/components/ui/skeleton'
export default function ArticlesLoading() {
return (
<div className="space-y-8">
{/* Title (24px) + export menu + "Ny artikel" action (pills) */}
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<Skeleton className="h-8 w-32" />
<div className="flex gap-2">
<Skeleton className="h-9 w-28 rounded-full" />
<Skeleton className="h-9 w-28 rounded-full" />
</div>
</div>
{/* Search toolbar */}
<Skeleton className="h-9 w-full" />
{/* Borderless table: header row + single-line rows */}
<div>
<div className="flex h-10 items-center gap-4 border-b border-border px-4">
<Skeleton className="h-3 w-24" />
<Skeleton className="ml-auto h-3 w-14" />
</div>
{[1, 2, 3, 4, 5, 6].map((i) => (
<div
key={i}
className="flex items-center justify-between gap-4 border-b border-border px-4 py-3 last:border-b-0"
>
<Skeleton className="h-4 w-40" />
<div className="flex items-center gap-6">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-4 w-20" />
</div>
</div>
))}
</div>
</div>
)
}