refactor(frontend): migrate skeleton patterns to Skeleton component (7 files)
77 animate-pulse instances replaced with <Skeleton> from $lib/ui: - dashboards/+page (48 instances — loading grid) - datasets/[id]/+page (6), maintenance/+page (6), settings/+page (5) - reports/llm/[taskId]/+page (3), dashboards/[id]/+page (8) - validation-tasks/+page (1 — table skeleton with row variant)
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
import DashboardMaintenanceBadge from "$lib/components/DashboardMaintenanceBadge.svelte";
|
||||
|
||||
import { environmentContextStore, initializeEnvironmentContext, setSelectedEnvironment } from "$lib/stores/environmentContext.svelte.js";
|
||||
import { Button } from "$lib/ui";
|
||||
import { Button, Skeleton } from "$lib/ui";
|
||||
import ColumnFilterPopover from "./ColumnFilterPopover.svelte";
|
||||
import { formatDate, getPaginationRange, getSortIndicator } from "./dashboard-helpers.js";
|
||||
import { DashboardHubModel } from "$lib/models/DashboardHubModel.svelte.ts";
|
||||
@@ -158,28 +158,28 @@
|
||||
class="grid gap-4 px-6 py-3 bg-surface-muted border-b border-border font-semibold text-[11px] uppercase tracking-wide text-text-muted"
|
||||
style="width: max(100%, 1460px); grid-template-columns: 40px minmax(250px,2.3fr) minmax(118px,0.9fr) minmax(70px,0.5fr) minmax(110px,0.7fr) minmax(280px,2fr) minmax(150px,1fr) 124px;"
|
||||
>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
</div>
|
||||
{#each Array(5) as _}
|
||||
<div
|
||||
class="grid gap-4 px-6 py-4 border-b border-border last:border-b-0 hover:bg-surface-muted transition-colors"
|
||||
style="width: max(100%, 1460px); grid-template-columns: 40px minmax(250px,2.3fr) minmax(118px,0.9fr) minmax(70px,0.5fr) minmax(110px,0.7fr) minmax(280px,2fr) minmax(150px,1fr) 124px;"
|
||||
>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<div class="h-4 rounded bg-surface-muted animate-pulse"></div>
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
<Skeleton variant="line" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import { openDrawerForTaskIfPreferred } from '$lib/stores/taskDrawer.svelte.js';
|
||||
import { DashboardDetailModel } from '$lib/models/DashboardDetailModel.svelte';
|
||||
import { ROUTES } from '$lib/routes.js';
|
||||
import { Skeleton } from '$lib/ui';
|
||||
|
||||
import CommitHistory from '$lib/components/git/CommitHistory.svelte';
|
||||
import GitManager from '$lib/components/git/GitManager.svelte';
|
||||
@@ -67,10 +68,10 @@
|
||||
{#if m.isLoading}
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
{#each Array(3) as _}
|
||||
<div class="h-24 animate-pulse rounded-xl border border-border bg-surface-card"></div>
|
||||
<Skeleton variant="card" height="h-24" class="rounded-xl border border-border bg-surface-card" />
|
||||
{/each}
|
||||
</div>
|
||||
<div class="h-64 animate-pulse rounded-xl border border-border bg-surface-card"></div>
|
||||
<Skeleton variant="card" height="h-64" class="rounded-xl border border-border bg-surface-card" />
|
||||
{:else if m.dashboard}
|
||||
<div class="grid grid-cols-1 gap-6 xl:grid-cols-5">
|
||||
<!-- Thumbnail -->
|
||||
@@ -80,7 +81,7 @@
|
||||
<button class="rounded-md border border-border-strong px-2 py-1 text-xs text-text hover:bg-surface-page" onclick={() => m.loadThumbnail(true)} disabled={m.isThumbnailLoading}>{$t.common?.refresh}</button>
|
||||
</div>
|
||||
{#if m.isThumbnailLoading}
|
||||
<div class="h-56 animate-pulse rounded-lg bg-surface-muted"></div>
|
||||
<Skeleton variant="card" height="h-56" />
|
||||
{:else if m.thumbnailUrl}
|
||||
<img src={m.thumbnailUrl} alt="Dashboard thumbnail" class="h-56 w-full rounded-lg border border-border object-cover" />
|
||||
{:else}
|
||||
@@ -136,7 +137,7 @@
|
||||
<button class="rounded-md border border-border-strong px-2 py-1 text-xs text-text hover:bg-surface-page" onclick={() => m.loadValidationHistory(m.dashboard?.id ?? m.dashboardRef)} disabled={m.isValidationHistoryLoading}>{$t.common?.refresh}</button>
|
||||
</div>
|
||||
{#if m.isValidationHistoryLoading}
|
||||
<div class="space-y-2">{#each Array(3) as _}<div class="h-10 animate-pulse rounded bg-surface-muted"></div>{/each}</div>
|
||||
<div class="space-y-2">{#each Array(3) as _}<Skeleton variant="line" height="h-10" />{/each}</div>
|
||||
{:else if m.validationHistoryError}
|
||||
<div class="rounded-lg border border-destructive-ring bg-destructive-light px-3 py-2 text-sm text-destructive">{m.validationHistoryError}</div>
|
||||
{:else if m.validationHistory.length === 0}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/state';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { Button } from '$lib/ui';
|
||||
import { Button, Skeleton } from '$lib/ui';
|
||||
import { DatasetDetailModel } from '$lib/models/DatasetDetailModel.svelte';
|
||||
|
||||
let datasetId = $derived(page.params.id);
|
||||
@@ -65,21 +65,21 @@
|
||||
{#if model.isLoading}
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<div class="bg-surface-card border border-border rounded-lg p-6">
|
||||
<div class="animate-pulse bg-surface-muted rounded h-6 w-1/2 mb-4"></div>
|
||||
<Skeleton variant="line" width="w-1/2" height="h-6" class="mb-4" />
|
||||
{#each Array(5) as _}
|
||||
<div class="flex justify-between py-2 border-b border-border last:border-0">
|
||||
<div class="animate-pulse bg-surface-muted rounded h-4 w-20"></div>
|
||||
<div class="animate-pulse bg-surface-muted rounded h-4 w-32"></div>
|
||||
<Skeleton variant="line" width="w-20" />
|
||||
<Skeleton variant="line" width="w-32" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="bg-surface-card border border-border rounded-lg p-6 lg:col-span-2">
|
||||
<div class="animate-pulse bg-surface-muted rounded h-6 w-1/3 mb-4"></div>
|
||||
<Skeleton variant="line" width="w-1/3" height="h-6" class="mb-4" />
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{#each Array(4) as _}
|
||||
<div class="p-3 border border-border rounded-lg">
|
||||
<div class="animate-pulse bg-surface-muted rounded h-4 w-full mb-2"></div>
|
||||
<div class="animate-pulse bg-surface-muted rounded h-3 w-16"></div>
|
||||
<Skeleton variant="line" class="mb-2" />
|
||||
<Skeleton variant="line" width="w-16" height="h-3" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import MaintenanceEventsTable from "$lib/components/MaintenanceEventsTable.svelte";
|
||||
import StartMaintenanceForm from "$lib/components/StartMaintenanceForm.svelte";
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { Skeleton } from "$lib/ui";
|
||||
|
||||
let pageLoading = $state(true);
|
||||
|
||||
@@ -54,17 +55,17 @@
|
||||
<!-- Loading skeleton -->
|
||||
<div class="space-y-6">
|
||||
<div class="rounded-lg border border-border bg-surface-card p-4">
|
||||
<div class="animate-pulse bg-surface-muted h-6 w-40 rounded mb-4"></div>
|
||||
<Skeleton variant="line" width="w-40" height="h-6" class="mb-4" />
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="animate-pulse bg-surface-muted h-10 rounded"></div>
|
||||
<div class="animate-pulse bg-surface-muted h-10 rounded"></div>
|
||||
<Skeleton variant="line" height="h-10" />
|
||||
<Skeleton variant="line" height="h-10" />
|
||||
</div>
|
||||
<div class="mt-4 animate-pulse bg-surface-muted h-20 rounded"></div>
|
||||
<Skeleton variant="card" height="h-20" class="mt-4" />
|
||||
</div>
|
||||
<div class="border border-border rounded-lg overflow-hidden">
|
||||
<div class="animate-pulse bg-surface-muted h-8 w-full"></div>
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
{#each [1, 2, 3] as _, i (i)}
|
||||
<div class="animate-pulse bg-surface-muted h-12 w-full border-t border-border"></div>
|
||||
<Skeleton variant="line" height="h-12" class="border-t border-border" />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { openDrawerForTask } from '$lib/stores/taskDrawer.svelte.js';
|
||||
import Icon from '$lib/ui/Icon.svelte';
|
||||
import { Skeleton } from '$lib/ui';
|
||||
import { LLMReportModel } from '$lib/models/LLMReportModel.svelte';
|
||||
|
||||
let taskId = $derived(page.params.taskId);
|
||||
@@ -92,9 +93,9 @@
|
||||
|
||||
{#if model.screenState === 'loading'}
|
||||
<div class="space-y-3">
|
||||
<div class="h-24 animate-pulse rounded-xl border border-border bg-surface-card"></div>
|
||||
<div class="h-64 animate-pulse rounded-xl border border-border bg-surface-card"></div>
|
||||
<div class="h-64 animate-pulse rounded-xl border border-border bg-surface-card"></div>
|
||||
<Skeleton variant="card" height="h-24" class="rounded-xl border border-border bg-surface-card" />
|
||||
<Skeleton variant="card" height="h-64" class="rounded-xl border border-border bg-surface-card" />
|
||||
<Skeleton variant="card" height="h-64" class="rounded-xl border border-border bg-surface-card" />
|
||||
</div>
|
||||
{:else if model.task}
|
||||
<!-- Stats row -->
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
import { t } from "$lib/i18n/index.svelte.js";
|
||||
import { api } from "$lib/api.js";
|
||||
import { addToast } from "$lib/toasts.svelte.js";
|
||||
import { Skeleton } from "$lib/ui";
|
||||
|
||||
import {
|
||||
normalizeTab,
|
||||
@@ -137,11 +138,11 @@
|
||||
{#if isLoading}
|
||||
<div class="rounded-xl border border-border bg-surface-card p-6 shadow-sm">
|
||||
<div class="space-y-3">
|
||||
<div class="h-8 animate-pulse rounded bg-surface-muted"></div>
|
||||
<div class="h-8 animate-pulse rounded bg-surface-muted"></div>
|
||||
<div class="h-8 animate-pulse rounded bg-surface-muted"></div>
|
||||
<div class="h-8 animate-pulse rounded bg-surface-muted"></div>
|
||||
<div class="h-8 animate-pulse rounded bg-surface-muted"></div>
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
<Skeleton variant="line" height="h-8" />
|
||||
</div>
|
||||
</div>
|
||||
{:else if settings}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '$lib/i18n/index.svelte.js';
|
||||
import { EmptyState } from '$lib/ui';
|
||||
import { EmptyState, Skeleton } from '$lib/ui';
|
||||
import { ValidationTasksListModel } from '$lib/models/ValidationTasksListModel.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
@@ -92,20 +92,8 @@
|
||||
|
||||
<!-- Loading -->
|
||||
{#if m.isLoading}
|
||||
<div class="bg-surface-card border border-border rounded-lg overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-border">
|
||||
<thead class="bg-surface-muted"><tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.task_name}</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.environment}</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.schedule}</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.last_run}</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.status}</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-text-muted uppercase tracking-wider">{$t.validation?.actions}</th>
|
||||
</tr></thead>
|
||||
<tbody class="bg-surface-card divide-y divide-border">
|
||||
{#each Array(5) as _, i (i)}<tr class="animate-pulse"><td class="px-6 py-4"><div class="h-4 w-40 bg-surface-muted rounded"></div></td><td class="px-6 py-4"><div class="h-4 w-24 bg-surface-muted rounded"></div></td><td class="px-6 py-4"><div class="h-4 w-20 bg-surface-muted rounded"></div></td><td class="px-6 py-4"><div class="h-4 w-32 bg-surface-muted rounded"></div></td><td class="px-6 py-4"><div class="h-5 w-14 bg-surface-muted rounded-full"></div></td><td class="px-6 py-4"><div class="h-4 w-24 bg-surface-muted rounded ml-auto"></div></td></tr>{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="bg-surface-card border border-border rounded-lg overflow-hidden p-6">
|
||||
<Skeleton variant="row" cols={6} rows={5} />
|
||||
</div>
|
||||
|
||||
<!-- Empty -->
|
||||
|
||||
Reference in New Issue
Block a user