Loading State Patterns
v1.0.0Patterns for skeleton loaders, shimmer effects, and loading states that match design system aesthetics. Covers skeleton components, shimmer animations, and progressive loading. Use when building polished loading experiences. Triggers on skeleton, loading state, shimmer, placeholder, loading animation.
Security Scan
OpenClaw
Benign
high confidencePurpose & Capability
The name and description match the content: SKILL.md contains only UI patterns, example components, and CSS for skeletons/shimmers. It does not request unrelated credentials, binaries, or configuration.
Instruction Scope
Runtime instructions are example code snippets and guidance for building loading states. The SKILL.md does not instruct the agent to read system files, environment variables, or contact external endpoints; it stays within the stated design-pattern scope.
Install Mechanism
There is no install spec and no code files beyond documentation. README contains optional manual install copy instructions (local filesystem paths) and an npx example, but nothing will be automatically downloaded or executed by the platform.
Credentials
The skill declares no required environment variables, credentials, or config paths. The SKILL.md does not reference any secrets or external service tokens.
Persistence & Privilege
always is false and the skill does not request persistent or elevated privileges. It does not modify other skills or system settings in its instructions.
Assessment
This skill is an instruction-only collection of React/CSS examples for loading states and appears internally consistent. Before installing or copying code: (1) review the snippets to ensure they fit your coding standards and licenses, (2) be cautious with the README's manual install suggestions — they reference local paths (~/.ai-skills) and a GitHub tree URL that may not be directly installable with npx, so verify the source repository and trustworthiness, and (3) because the skill’s source/homepage is 'unknown', confirm the origin if you intend to include these patterns in production. No credentials or system access are requested by this skill.Like a lobster shell, security has layers — review code before you run it.
latest
Loading State Patterns
Build loading states that feel intentional and match your design system aesthetic.
When to Use
- Building skeleton loaders for content areas
- Need shimmer effects for streaming content
- Want progressive loading experiences
- Building premium loading UX
Pattern 1: Skeleton Base
import { cn } from '@/lib/utils';
interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
shimmer?: boolean;
}
export function Skeleton({ className, shimmer = true, ...props }: SkeletonProps) {
return (
<div
className={cn(
'rounded-md bg-muted',
shimmer && 'animate-shimmer bg-gradient-to-r from-muted via-muted-foreground/10 to-muted bg-[length:200%_100%]',
className
)}
{...props}
/>
);
}
CSS Animation
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.animate-shimmer {
animation: shimmer 1.5s ease-in-out infinite;
}
Pattern 2: Content Skeleton Layouts
Card Skeleton
export function CardSkeleton() {
return (
<div className="rounded-lg border bg-card p-4 space-y-3">
<div className="flex items-center gap-3">
<Skeleton className="size-10 rounded-full" />
<div className="space-y-1.5 flex-1">
<Skeleton className="h-4 w-1/3" />
<Skeleton className="h-3 w-1/4" />
</div>
</div>
<Skeleton className="h-20 w-full" />
<div className="flex gap-2">
<Skeleton className="h-8 w-20" />
<Skeleton className="h-8 w-20" />
</div>
</div>
);
}
Table Row Skeleton
export function TableRowSkeleton({ columns = 4 }: { columns?: number }) {
return (
<tr>
{Array.from({ length: columns }).map((_, i) => (
<td key={i} className="p-3">
<Skeleton className="h-4 w-full" />
</td>
))}
</tr>
);
}
Metric Skeleton
export function MetricSkeleton() {
return (
<div className="space-y-2">
<Skeleton className="h-3 w-16" />
<Skeleton className="h-8 w-24" />
</div>
);
}
Pattern 3: Design System Skeleton
Match skeleton to your aesthetic:
// For retro-futuristic theme
export function CyberSkeleton({ className, ...props }: SkeletonProps) {
return (
<div
className={cn(
'rounded-md bg-tone-cadet/30',
'animate-pulse-glow',
'border border-tone-cyan/10',
className
)}
{...props}
/>
);
}
// CSS
@keyframes pulse-glow {
0%, 100% { opacity: 0.4; box-shadow: 0 0 0 0 rgba(var(--tone-cyan), 0); }
50% { opacity: 0.6; box-shadow: 0 0 8px 0 rgba(var(--tone-cyan), 0.1); }
}
Pattern 4: Progressive Loading
Show content as it loads:
interface ProgressiveLoadProps {
isLoading: boolean;
skeleton: React.ReactNode;
children: React.ReactNode;
}
export function ProgressiveLoad({
isLoading,
skeleton,
children,
}: ProgressiveLoadProps) {
return (
<div className="relative">
{isLoading ? (
skeleton
) : (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}
>
{children}
</motion.div>
)}
</div>
);
}
Pattern 5: Streaming Content Indicator
For AI/LLM content that streams:
export function StreamingIndicator() {
return (
<div className="flex items-center gap-1">
{[0, 1, 2].map((i) => (
<motion.div
key={i}
className="size-1.5 rounded-full bg-primary"
animate={{ scale: [1, 1.3, 1], opacity: [0.5, 1, 0.5] }}
transition={{
duration: 0.8,
repeat: Infinity,
delay: i * 0.15,
}}
/>
))}
</div>
);
}
Pattern 6: Loading Progress Bar
interface LoadingProgressProps {
progress?: number; // 0-100, undefined = indeterminate
}
export function LoadingProgress({ progress }: LoadingProgressProps) {
const isIndeterminate = progress === undefined;
return (
<div className="h-1 w-full bg-muted overflow-hidden rounded-full">
<div
className={cn(
'h-full bg-primary transition-all duration-300',
isIndeterminate && 'animate-indeterminate'
)}
style={!isIndeterminate ? { width: `${progress}%` } : undefined}
/>
</div>
);
}
// CSS
@keyframes indeterminate {
0% { transform: translateX(-100%); width: 50%; }
100% { transform: translateX(200%); width: 50%; }
}
.animate-indeterminate {
animation: indeterminate 1.5s ease-in-out infinite;
}
Pattern 7: Skeleton Grid
export function GridSkeleton({
count = 6,
columns = 3
}: {
count?: number;
columns?: number;
}) {
return (
<div
className="grid gap-4"
style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}
>
{Array.from({ length: count }).map((_, i) => (
<CardSkeleton key={i} />
))}
</div>
);
}
Related Skills
- Meta-skill: ai/skills/meta/design-system-creation/ — Complete design system workflow
- distinctive-design-systems — Aesthetic matching for themed skeletons
NEVER Do
- Use gray skeletons on dark themes — Match your surface colors
- Skip shimmer animation — Static blocks look broken
- Make skeletons exact size — Slight size variation is natural
- Forget aspect ratios — Images need consistent skeleton ratios
- Show skeleton forever — Add timeout fallbacks for errors
Quick Reference
// Basic skeleton
<Skeleton className="h-4 w-full" />
// Avatar skeleton
<Skeleton className="size-10 rounded-full" />
// Text lines
<div className="space-y-2">
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-1/2" />
</div>
// Card skeleton
<div className="p-4 space-y-3">
<Skeleton className="h-6 w-1/3" />
<Skeleton className="h-20 w-full" />
</div>
Comments
Loading comments...
