/install loading-state-patterns
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\x3CHTMLDivElement> {
shimmer?: boolean;
}
export function Skeleton({ className, shimmer = true, ...props }: SkeletonProps) {
return (
\x3Cdiv
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 (
\x3Cdiv className="rounded-lg border bg-card p-4 space-y-3">
\x3Cdiv className="flex items-center gap-3">
\x3CSkeleton className="size-10 rounded-full" />
\x3Cdiv className="space-y-1.5 flex-1">
\x3CSkeleton className="h-4 w-1/3" />
\x3CSkeleton className="h-3 w-1/4" />
\x3C/div>
\x3C/div>
\x3CSkeleton className="h-20 w-full" />
\x3Cdiv className="flex gap-2">
\x3CSkeleton className="h-8 w-20" />
\x3CSkeleton className="h-8 w-20" />
\x3C/div>
\x3C/div>
);
}
Table Row Skeleton
export function TableRowSkeleton({ columns = 4 }: { columns?: number }) {
return (
\x3Ctr>
{Array.from({ length: columns }).map((_, i) => (
\x3Ctd key={i} className="p-3">
\x3CSkeleton className="h-4 w-full" />
\x3C/td>
))}
\x3C/tr>
);
}
Metric Skeleton
export function MetricSkeleton() {
return (
\x3Cdiv className="space-y-2">
\x3CSkeleton className="h-3 w-16" />
\x3CSkeleton className="h-8 w-24" />
\x3C/div>
);
}
Pattern 3: Design System Skeleton
Match skeleton to your aesthetic:
// For retro-futuristic theme
export function CyberSkeleton({ className, ...props }: SkeletonProps) {
return (
\x3Cdiv
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 (
\x3Cdiv className="relative">
{isLoading ? (
skeleton
) : (
\x3Cmotion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}
>
{children}
\x3C/motion.div>
)}
\x3C/div>
);
}
Pattern 5: Streaming Content Indicator
For AI/LLM content that streams:
export function StreamingIndicator() {
return (
\x3Cdiv className="flex items-center gap-1">
{[0, 1, 2].map((i) => (
\x3Cmotion.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,
}}
/>
))}
\x3C/div>
);
}
Pattern 6: Loading Progress Bar
interface LoadingProgressProps {
progress?: number; // 0-100, undefined = indeterminate
}
export function LoadingProgress({ progress }: LoadingProgressProps) {
const isIndeterminate = progress === undefined;
return (
\x3Cdiv className="h-1 w-full bg-muted overflow-hidden rounded-full">
\x3Cdiv
className={cn(
'h-full bg-primary transition-all duration-300',
isIndeterminate && 'animate-indeterminate'
)}
style={!isIndeterminate ? { width: `${progress}%` } : undefined}
/>
\x3C/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 (
\x3Cdiv
className="grid gap-4"
style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}
>
{Array.from({ length: count }).map((_, i) => (
\x3CCardSkeleton key={i} />
))}
\x3C/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
\x3CSkeleton className="h-4 w-full" />
// Avatar skeleton
\x3CSkeleton className="size-10 rounded-full" />
// Text lines
\x3Cdiv className="space-y-2">
\x3CSkeleton className="h-4 w-3/4" />
\x3CSkeleton className="h-4 w-1/2" />
\x3C/div>
// Card skeleton
\x3Cdiv className="p-4 space-y-3">
\x3CSkeleton className="h-6 w-1/3" />
\x3CSkeleton className="h-20 w-full" />
\x3C/div>
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install loading-state-patterns - After installation, invoke the skill by name or use
/loading-state-patterns - Provide required inputs per the skill's parameter spec and get structured output
What is Loading State Patterns?
Patterns 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. It is an AI Agent Skill for Claude Code / OpenClaw, with 797 downloads so far.
How do I install Loading State Patterns?
Run "/install loading-state-patterns" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Loading State Patterns free?
Yes, Loading State Patterns is completely free (open-source). You can download, install and use it at no cost.
Which platforms does Loading State Patterns support?
Loading State Patterns is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Loading State Patterns?
It is built and maintained by wpank (@wpank); the current version is v1.0.0.