style: atualiza loadings e skeletons do dashboard

This commit is contained in:
Felipe Coutinho
2026-03-15 23:23:53 +00:00
parent e84becd1cd
commit 1823b6be56
23 changed files with 292 additions and 279 deletions

View File

@@ -1,43 +1,44 @@
import { Skeleton } from "@/shared/components/ui/skeleton";
/**
* Skeleton para o card de resumo da conta (AccountStatementCard)
* Reflete fielmente o layout: logo + nome + tipo + badge + métricas
*/
export function AccountStatementCardSkeleton() {
return (
<div className="rounded-2xl border p-6 space-y-6">
{/* Header com logo, nome, tipo e badge */}
<div className="flex items-start justify-between">
<div className="flex items-start gap-4">
{/* Logo */}
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
<div className="rounded-xl border px-4 py-4 sm:px-5 sm:py-5">
<div className="flex flex-col gap-4">
{/* Linha 1 — identidade */}
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-3">
<Skeleton className="size-12 shrink-0 rounded-full bg-foreground/10" />
<div className="space-y-1.5">
<Skeleton className="h-4 w-36 rounded bg-foreground/10" />
<Skeleton className="h-3 w-28 rounded bg-foreground/10" />
</div>
</div>
<Skeleton className="size-7 rounded bg-foreground/10" />
</div>
<div className="space-y-2">
{/* Nome da conta */}
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
{/* Tipo de conta */}
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
{/* Linha 2 — saldo hero */}
<div className="space-y-2">
<Skeleton className="h-3 w-40 rounded bg-foreground/10" />
<Skeleton className="h-9 w-44 rounded bg-foreground/10" />
<div className="flex gap-2">
<Skeleton className="h-5 w-12 rounded-full bg-foreground/10" />
<Skeleton className="h-5 w-20 rounded bg-foreground/10" />
</div>
</div>
<div className="flex items-center gap-2">
{/* Badge de status */}
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
{/* Botão de editar */}
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
{/* Linha 3 — breakdown */}
<div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
{Array.from({ length: 4 }).map((_, i) => (
<div
key={i}
className="rounded-md border border-border/60 px-3 py-2 space-y-1.5"
>
<Skeleton className="h-3 w-16 rounded bg-foreground/10" />
<Skeleton className="h-5 w-24 rounded bg-foreground/10" />
</div>
))}
</div>
</div>
{/* Métricas em grid */}
<div className="grid grid-cols-2 gap-4 pt-4 border-t md:grid-cols-4">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="space-y-2">
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-32 rounded-2xl bg-foreground/10" />
</div>
))}
</div>
</div>
);
}

View File

@@ -23,16 +23,16 @@ export function CategoryReportSkeleton() {
<div className="flex flex-wrap items-center justify-between gap-2">
<div className="flex flex-wrap items-center gap-2">
{/* Category MultiSelect */}
<Skeleton className="h-10 w-[200px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[200px] rounded-md bg-foreground/10" />
{/* Start Period */}
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[150px] rounded-md bg-foreground/10" />
{/* End Period */}
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[150px] rounded-md bg-foreground/10" />
{/* Clear Button */}
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-8 w-16 rounded-md bg-foreground/10" />
</div>
{/* Export Button */}
<Skeleton className="h-10 w-[120px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[120px] rounded-md bg-foreground/10" />
</div>
</div>
@@ -40,8 +40,8 @@ export function CategoryReportSkeleton() {
<Tabs value="table" className="w-full">
<TabsList>
<div className="flex gap-1">
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[100px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[100px] rounded-md bg-foreground/10" />
<Skeleton className="h-10 w-[100px] rounded-md bg-foreground/10" />
</div>
</TabsList>
@@ -58,11 +58,11 @@ export function CategoryReportSkeleton() {
<div className="space-y-3">
{/* Category name with icon */}
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
<Skeleton className="size-4 rounded-md bg-foreground/10" />
<Skeleton className="h-5 w-32 rounded-md bg-foreground/10" />
</div>
{/* Type badge */}
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-20 rounded-md bg-foreground/10" />
{/* Values */}
<div className="space-y-2">
{Array.from({ length: 3 }).map((_, j) => (
@@ -70,8 +70,8 @@ export function CategoryReportSkeleton() {
key={j}
className="flex items-center justify-between"
>
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-24 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</div>
))}
</div>
@@ -87,17 +87,17 @@ export function CategoryReportSkeleton() {
<div className="space-y-4">
{/* Chart title area */}
<div className="flex items-center justify-between">
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-48 rounded-md bg-foreground/10" />
<Skeleton className="h-8 w-32 rounded-md bg-foreground/10" />
</div>
{/* Chart area */}
<Skeleton className="h-[400px] w-full rounded-2xl bg-foreground/10" />
<Skeleton className="h-[400px] w-full rounded-md bg-foreground/10" />
{/* Legend */}
<div className="flex flex-wrap gap-4 justify-center">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="flex items-center gap-2">
<Skeleton className="size-3 rounded-full bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</div>
))}
</div>
@@ -124,17 +124,17 @@ function CategoryReportTableSkeleton() {
<TableRow>
{/* Category */}
<TableHead className="w-[280px] min-w-[280px]">
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</TableHead>
{/* Period columns */}
{Array.from({ length: periodColumns }).map((_, i) => (
<TableHead key={i} className="text-right min-w-[120px]">
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10 ml-auto" />
<Skeleton className="h-4 w-16 rounded-md bg-foreground/10 ml-auto" />
</TableHead>
))}
{/* Total */}
<TableHead className="text-right min-w-[120px]">
<Skeleton className="h-4 w-10 rounded-2xl bg-foreground/10 ml-auto" />
<Skeleton className="h-4 w-10 rounded-md bg-foreground/10 ml-auto" />
</TableHead>
</TableRow>
</TableHeader>
@@ -146,24 +146,24 @@ function CategoryReportTableSkeleton() {
<TableCell>
<div className="flex items-center gap-2">
<Skeleton className="size-2 rounded-full bg-foreground/10" />
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-32 rounded-2xl bg-foreground/10" />
<Skeleton className="size-4 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-32 rounded-md bg-foreground/10" />
</div>
</TableCell>
{/* Period values */}
{Array.from({ length: periodColumns }).map((_, colIndex) => (
<TableCell key={colIndex} className="text-right">
<div className="flex flex-col items-end gap-1">
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
{colIndex > 0 && (
<Skeleton className="h-3 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-3 w-16 rounded-md bg-foreground/10" />
)}
</div>
</TableCell>
))}
{/* Total */}
<TableCell className="text-right">
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-24 rounded-md bg-foreground/10" />
</TableCell>
</TableRow>
))}
@@ -173,17 +173,17 @@ function CategoryReportTableSkeleton() {
<TableRow>
{/* Total label */}
<TableCell className="font-bold">
<Skeleton className="h-5 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-5 w-16 rounded-md bg-foreground/10" />
</TableCell>
{/* Period totals */}
{Array.from({ length: periodColumns }).map((_, i) => (
<TableCell key={i} className="text-right">
<Skeleton className="h-5 w-24 rounded-2xl bg-foreground/10 ml-auto" />
<Skeleton className="h-5 w-24 rounded-md bg-foreground/10 ml-auto" />
</TableCell>
))}
{/* Grand total */}
<TableCell className="text-right">
<Skeleton className="h-5 w-28 rounded-2xl bg-foreground/10 ml-auto" />
<Skeleton className="h-5 w-28 rounded-md bg-foreground/10 ml-auto" />
</TableCell>
</TableRow>
</TableFooter>

View File

@@ -1,17 +1,21 @@
import { DashboardMetricsCardsSkeleton } from "./dashboard-metrics-cards-skeleton";
import { Skeleton } from "@/shared/components/ui/skeleton";
import { WidgetSkeleton } from "./widget-skeleton";
/**
* Skeleton completo para o dashboard grid
* Mantém a mesma estrutura de layout do dashboard real
*/
export function DashboardGridSkeleton() {
return (
<div className="@container/main space-y-4">
{/* Cards de métricas no topo */}
<DashboardMetricsCardsSkeleton />
<div className="flex flex-wrap items-center justify-between gap-2">
<div className="grid w-full grid-cols-3 gap-1 sm:flex sm:w-auto sm:items-center sm:gap-2">
<Skeleton className="h-12 rounded-md bg-foreground/10 sm:h-8 sm:w-28" />
<Skeleton className="h-12 rounded-md bg-foreground/10 sm:h-8 sm:w-30" />
<Skeleton className="h-12 rounded-md bg-foreground/10 sm:h-8 sm:w-28" />
</div>
<div className="flex w-full gap-2 sm:w-auto">
<Skeleton className="h-10 flex-1 rounded-md bg-foreground/10 sm:h-8 sm:w-34 sm:flex-none" />
<Skeleton className="h-10 flex-1 rounded-md bg-foreground/10 sm:h-8 sm:w-24 sm:flex-none" />
</div>
</div>
{/* Grid de widgets - mesmos breakpoints do dashboard real */}
<div className="grid grid-cols-1 gap-3 @4xl/main:grid-cols-2 @6xl/main:grid-cols-3">
{Array.from({ length: 9 }).map((_, i) => (
<WidgetSkeleton key={i} />

View File

@@ -1,34 +1,35 @@
import { Card, CardFooter, CardHeader } from "@/shared/components/ui/card";
import {
Card,
CardFooter,
CardHeader,
CardTitle,
} from "@/shared/components/ui/card";
import { Skeleton } from "@/shared/components/ui/skeleton";
/**
* Skeleton fiel aos cards de métricas do dashboard (DashboardMetricsCards)
* Mantém o mesmo layout de 4 colunas responsivo
*/
export function DashboardMetricsCardsSkeleton() {
return (
<div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
<div className="grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
{Array.from({ length: 4 }).map((_, index) => (
<Card key={index} className="@container/card gap-2">
<Card
key={index}
className="@container/card flex flex-col justify-between min-h-32"
>
<CardHeader>
<div className="space-y-3">
{/* Título com ícone */}
<div className="flex items-center gap-1">
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
<Skeleton className="h-5 w-20 rounded-2xl bg-foreground/10" />
</div>
{/* Valor principal */}
<Skeleton className="h-8 w-32 rounded-2xl bg-foreground/10" />
{/* Badge de tendência */}
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
<CardTitle className="flex items-center gap-1">
<Skeleton className="size-4 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</CardTitle>
<div className="flex items-baseline gap-2 mt-auto pt-4">
<Skeleton className="h-9 w-32 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-12 rounded-md bg-foreground/10" />
</div>
</CardHeader>
<CardFooter className="flex-col items-start gap-1.5 text-sm">
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<CardFooter className="text-sm">
<div className="flex items-center gap-1.5">
<Skeleton className="h-3 w-20 rounded-md bg-foreground/10" />
<Skeleton className="h-3 w-16 rounded-md bg-foreground/10" />
</div>
</CardFooter>
</Card>
))}

View File

@@ -10,11 +10,11 @@ export function FilterSkeleton() {
{Array.from({ length: 6 }).map((_, i) => (
<Skeleton
key={i}
className="h-10 w-[130px] rounded-2xl bg-foreground/10"
className="h-10 w-[130px] rounded-md bg-foreground/10"
/>
))}
<Skeleton className="h-10 w-[150px] rounded-2xl bg-foreground/10" />
<Skeleton className="h-8 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-10 w-[150px] rounded-md bg-foreground/10" />
<Skeleton className="h-8 w-16 rounded-md bg-foreground/10" />
</div>
);
}

View File

@@ -6,58 +6,54 @@ import { Skeleton } from "@/shared/components/ui/skeleton";
*/
export function InvoiceSummaryCardSkeleton() {
return (
<div className="rounded-2xl border p-6 space-y-6">
{/* Header com logo, nome, bandeira e badges */}
<div className="flex items-start justify-between">
<div className="flex items-start gap-4">
{/* Logo do cartão */}
<Skeleton className="size-12 rounded-2xl bg-foreground/10" />
<div className="space-y-2">
{/* Nome do cartão */}
<Skeleton className="h-6 w-48 rounded-2xl bg-foreground/10" />
<div className="flex items-center gap-2">
{/* Bandeira */}
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
{/* Badge de status */}
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
</div>
<div className="rounded-md border p-4 space-y-4 sm:p-5">
<div className="flex items-center justify-between gap-3">
<div className="flex min-w-0 items-center gap-3">
<Skeleton className="size-12 rounded-full bg-foreground/10" />
<div className="min-w-0 space-y-2">
<Skeleton className="h-4 w-40 rounded-md bg-foreground/10" />
<Skeleton className="h-3 w-28 rounded-md bg-foreground/10" />
</div>
</div>
{/* Botão de editar */}
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
<Skeleton className="size-8 rounded-md bg-foreground/10" />
</div>
{/* Informações da fatura */}
<div className="space-y-4 pt-4 border-t">
{/* Período e status */}
<div className="flex items-center justify-between">
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-24 rounded-2xl bg-foreground/10" />
</div>
{/* Total da fatura */}
<div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
<div className="space-y-2">
<Skeleton className="h-4 w-28 rounded-2xl bg-foreground/10" />
<Skeleton className="h-8 w-40 rounded-2xl bg-foreground/10" />
</div>
{/* Limite e utilização */}
<div className="grid grid-cols-2 gap-4 pt-4">
<div className="space-y-2">
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
</div>
<div className="space-y-2">
<Skeleton className="h-4 w-24 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-28 rounded-2xl bg-foreground/10" />
<Skeleton className="h-3 w-24 rounded-md bg-foreground/10" />
<Skeleton className="h-9 w-44 rounded-md bg-foreground/10" />
<div className="flex items-center gap-2">
<Skeleton className="h-6 w-20 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-28 rounded-md bg-foreground/10" />
</div>
</div>
{/* Botão de ação */}
<Skeleton className="h-10 w-full rounded-2xl bg-foreground/10" />
<div className="grid grid-cols-2 gap-2">
<Skeleton className="h-14 w-full rounded-md bg-foreground/10" />
<Skeleton className="h-14 w-full rounded-md bg-foreground/10" />
</div>
</div>
<div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
{Array.from({ length: 4 }).map((_, i) => (
<Skeleton
key={i}
className="h-14 w-full rounded-md bg-foreground/10"
/>
))}
</div>
<div className="rounded-md border border-dashed p-3">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="space-y-2">
<Skeleton className="h-4 w-24 rounded-md bg-foreground/10" />
<Skeleton className="h-3 w-40 rounded-md bg-foreground/10" />
</div>
<div className="flex items-center gap-2">
<Skeleton className="h-9 w-32 rounded-md bg-foreground/10" />
<Skeleton className="size-8 rounded-md bg-foreground/10" />
</div>
</div>
</div>
</div>
);

View File

@@ -14,7 +14,7 @@ import {
*/
export function TransactionsTableSkeleton() {
return (
<div className="rounded-2xl border">
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
@@ -24,8 +24,8 @@ export function TransactionsTableSkeleton() {
<TableHead className="w-[120px]">Valor</TableHead>
<TableHead className="w-[120px]">Condição</TableHead>
<TableHead className="w-[120px]">Pagamento</TableHead>
<TableHead className="w-[140px]">Payer</TableHead>
<TableHead className="w-[140px]">Category</TableHead>
<TableHead className="w-[140px]">Pagador</TableHead>
<TableHead className="w-[140px]">Categoria</TableHead>
<TableHead className="w-[140px]">Conta/Cartão</TableHead>
<TableHead className="w-[80px]">Ações</TableHead>
</TableRow>
@@ -34,45 +34,45 @@ export function TransactionsTableSkeleton() {
{Array.from({ length: 8 }).map((_, i) => (
<TableRow key={i}>
<TableCell>
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-full rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-16 rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-20 rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<Skeleton className="h-6 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-16 rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-20 rounded-md bg-foreground/10" />
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Skeleton className="size-6 rounded-full bg-foreground/10" />
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-16 rounded-md bg-foreground/10" />
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-16 rounded-2xl bg-foreground/10" />
<Skeleton className="size-4 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-16 rounded-md bg-foreground/10" />
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Skeleton className="size-6 rounded-2xl bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="size-6 rounded-md bg-foreground/10" />
<Skeleton className="h-4 w-20 rounded-md bg-foreground/10" />
</div>
</TableCell>
<TableCell>
<div className="flex gap-1">
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
<Skeleton className="size-8 rounded-2xl bg-foreground/10" />
<Skeleton className="size-8 rounded-md bg-foreground/10" />
<Skeleton className="size-8 rounded-md bg-foreground/10" />
</div>
</TableCell>
</TableRow>

View File

@@ -1,40 +1,40 @@
import { Card, CardContent, CardHeader } from "@/shared/components/ui/card";
import { Skeleton } from "@/shared/components/ui/skeleton";
/**
* Skeleton fiel ao WidgetCard
* Usado enquanto widgets do dashboard estão carregando
*/
const LINE_WIDTHS = ["w-full", "w-5/6", "w-4/5", "w-full", "w-3/4"] as const;
const SUBLABEL_WIDTHS = ["w-24", "w-16", "w-20", "w-28", "w-16"] as const;
export function WidgetSkeleton() {
return (
<Card className="relative h-auto gap-0 py-0 md:h-custom-height-card md:overflow-hidden">
<CardHeader className="border-b px-6 py-4">
<div className="flex w-full items-start justify-between">
<div className="min-w-0 space-y-1.5">
{/* Title com ícone */}
<div className="flex items-center gap-2">
<Skeleton className="size-4 rounded-2xl bg-foreground/10" />
<Skeleton className="h-5 w-32 rounded-2xl bg-foreground/10" />
<Skeleton className="size-4 rounded-md bg-foreground/10" />
<Skeleton className="h-5 w-32 rounded-md bg-foreground/10" />
</div>
{/* Subtitle */}
<Skeleton className="h-3 w-48 rounded-2xl bg-foreground/10" />
<Skeleton className="h-3 w-48 rounded-md bg-foreground/10" />
</div>
</div>
</CardHeader>
<CardContent className="min-h-0 flex-1 overflow-hidden px-6 py-4">
<div className="flex flex-col gap-3">
{/* Simula 5 linhas de conteúdo */}
{Array.from({ length: 5 }).map((_, i) => (
<div key={i} className="flex items-center justify-between gap-3">
<div className="flex flex-1 items-center gap-3">
<Skeleton className="size-10 rounded-2xl bg-foreground/10" />
<Skeleton className="size-10 rounded-md bg-foreground/10" />
<div className="flex-1 space-y-2">
<Skeleton className="h-4 w-full rounded-2xl bg-foreground/10" />
<Skeleton className="h-3 w-24 rounded-2xl bg-foreground/10" />
<Skeleton
className={`h-4 ${LINE_WIDTHS[i % LINE_WIDTHS.length]} rounded-md bg-foreground/10`}
/>
<Skeleton
className={`h-3 ${SUBLABEL_WIDTHS[i % SUBLABEL_WIDTHS.length]} rounded-md bg-foreground/10`}
/>
</div>
</div>
<Skeleton className="h-6 w-20 rounded-2xl bg-foreground/10" />
<Skeleton className="h-6 w-20 rounded-md bg-foreground/10" />
</div>
))}
</div>