Loading and Skeleton Components
The shared loading components at frontend/shared/src/components/Loading/ provide consistent loading indicators across all workbenches, including spinners, skeleton placeholders, loading overlays, and animated dots.
Components
LoadingSpinner
File: frontend/shared/src/components/Loading/LoadingSpinner.tsx
A configurable spinning indicator with size and color variants. Used as the default loading indicator throughout the platform.
Skeleton
File: frontend/shared/src/components/Loading/Skeleton.tsx
Animated skeleton placeholders that match the layout of content being loaded. Supports various shapes (text lines, circles, rectangles) for creating realistic loading previews.
Has Storybook stories at Skeleton.stories.tsx demonstrating usage patterns for cards, tables, and form layouts.
LoadingOverlay
File: frontend/shared/src/components/Loading/LoadingOverlay.tsx
A full-container overlay with spinner and optional message text. Used for blocking operations like data exports, bulk operations, and initial data loads.
LoadingDots
File: frontend/shared/src/components/Loading/LoadingDots.tsx
Animated bouncing dots indicator used for chat/AI assistant "thinking" states and inline loading indicators.
Usage Patterns
// Spinner for button loading state
<button disabled={isLoading}>
{isLoading ? <LoadingSpinner size="sm" /> : 'Save'}
</button>
// Skeleton for content preview
{isLoading ? (
<div className="space-y-3">
<Skeleton variant="text" width="60%" />
<Skeleton variant="text" width="80%" />
<Skeleton variant="rectangle" height={200} />
</div>
) : (
<DashboardContent data={data} />
)}
// Overlay for blocking operations
<LoadingOverlay
visible={isExporting}
message="Exporting dashboard to PDF..."
/>
// Dots for AI thinking state
<div className="flex items-center gap-2">
<LoadingDots />
<span>Thinking...</span>
</div>Index Exports
// frontend/shared/src/components/Loading/index.ts
export { LoadingSpinner } from './LoadingSpinner';
export { Skeleton } from './Skeleton';
export { LoadingOverlay } from './LoadingOverlay';
export { LoadingDots } from './LoadingDots';