+ {/* Tab row placeholder */}
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+ ))}
+
+
+
+ );
+}
+
+/** Skeleton for the library page. */
+export function SkeletonLibrary({ rows = 8 }: { rows?: number }) {
+ return (
+
+
+ {/* Health card placeholder */}
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+
+
+
+
+ ))}
+
+ {/* Status table placeholder */}
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+ );
+}
+
/** Skeleton for the channels list page. */
export function SkeletonChannelsList({ rows = 4 }: { rows?: number }) {
return (
diff --git a/src/frontend/src/pages/Activity.tsx b/src/frontend/src/pages/Activity.tsx
index f803b11..e90d7d3 100644
--- a/src/frontend/src/pages/Activity.tsx
+++ b/src/frontend/src/pages/Activity.tsx
@@ -1,9 +1,10 @@
import { useState, useMemo, useCallback } from 'react';
-import { ActivityIcon, Clock, Loader, RefreshCw } from 'lucide-react';
+import { ActivityIcon, Clock, RefreshCw } from 'lucide-react';
import { Table, type Column } from '../components/Table';
import { StatusBadge } from '../components/StatusBadge';
import { Pagination } from '../components/Pagination';
import { FilterBar, type FilterDefinition } from '../components/FilterBar';
+import { SkeletonActivityList } from '../components/Skeleton';
import { useHistory, useActivity, type HistoryFilters } from '../api/hooks/useActivity';
import type { DownloadHistoryRecord } from '@shared/types/index';
@@ -278,18 +279,7 @@ export function ActivityPage() {