From addg
Create skeleton loading components that mirror existing UI layout. Use when creating skeleton loaders, loading placeholders, Suspense fallbacks, Next.js loading.tsx files, or any visual placeholder that must match the final layout to prevent layout shift.
How this skill is triggered — by the user, by Claude, or both
Slash command
/addg:skeleton-loadingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create skeleton loading states that mirror existing UI layout, preserve responsiveness, and prevent layout shift. Skeletons are visual-only placeholders — never interactive.
Create skeleton loading states that mirror existing UI layout, preserve responsiveness, and prevent layout shift. Skeletons are visual-only placeholders — never interactive.
Always use the shared Skeleton component:
import { Skeleton } from '@/shared/components/ui/skeleton'
Follow these steps in order:
{component-name}-skeleton.tsx next to the source component.Skeleton elements — match dimensions using the sizing rules below.onClick, href, state, effects, and data fetching.{/* avatar */}, {/* title */}).Keep the container hierarchy identical to the source component. This prevents layout shift when content loads.
flex, grid, absolute, relative.sm:, md:, lg:, xl:.gap-*, p-*, m-*, w-*, h-*.Use w-full max-w-{value} instead of fixed w-{value} so skeletons adapt on smaller viewports.
// Do this — adapts to small screens
<Skeleton className="h-5 w-full max-w-32" />
// Not this — forces minimum width
<Skeleton className="h-5 w-32" />
Exception: Use fixed width for small elements that never exceed the viewport — icons (size-4, size-5), small standalone buttons.
When the original has explicit width: Preserve it exactly (e.g. w-full, w-1/2, or responsive w-48 md:w-64 lg:w-80).
Convert text line-height notation directly to skeleton height:
| Text class | Line height | Skeleton height |
|---|---|---|
text-sm/5 | 20px | h-5 |
text-base/6 | 24px | h-6 |
text-lg/7 | 28px | h-7 |
gap-1When creating multi-line skeletons for wrapping text and the original has no explicit gap between lines, use gap-1 (4px) between skeleton lines. Subtract 2px from each line height to compensate for the added gap and prevent layout shift:
| Single-line height | Multi-line height (with gap-1) |
|---|---|
h-5 (20px) | h-4.5 (18px) |
h-6 (24px) | h-5.5 (22px) |
h-7 (28px) | h-6.5 (26px) |
Why subtract 2px? The gap-1 adds 4px total between two lines. Subtracting 2px from each line (4px total) keeps the combined height identical.
Apply across all breakpoints: h-4.5 lg:h-5.5 for text-sm/5 lg:text-base/6.
When to apply: Only when the original has no explicit gap between text lines. If the original already has spacing (e.g. gap-2, space-y-1), match that spacing exactly without subtracting.
Long paragraph that wraps to multiple lines with no gap between lines.
```Skeleton:
{/* description (multi-line paragraph) */}
<div className="flex flex-col gap-1">
<Skeleton className="h-4.5 lg:h-5.5 w-full" />
<Skeleton className="h-4.5 lg:h-5.5 w-1/3" />
</div>
Skeleton matching line height and width. For paragraphs, use multiple lines and shorten the last one.<InfoIcon className="size-4" /> becomes <Skeleton className="size-4" />.rounded-full: <Avatar className="size-10" /> becomes <Skeleton className="size-10 rounded-full" />.rounded-full: <Skeleton className="h-6 w-20 rounded-full" />.Button, Link, or a tags.text-*, font-*, leading-*, tracking-* from skeleton elements (they have no text to style).{role}
Skeleton:
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3">
{/* avatar */}
<Skeleton className="size-10 rounded-full" />
<div className="flex flex-col gap-1">
{/* title */}
<Skeleton className="h-4 w-full max-w-32" />
{/* subtitle */}
<Skeleton className="h-3.5 w-full max-w-24" />
</div>
</div>
<div className="flex items-center gap-2">
{/* cancel button */}
<Skeleton className="h-8 w-16" />
{/* save button */}
<Skeleton className="h-8 w-12" />
</div>
</div>
Skeleton defaults to bg-accent. When the parent background is accented or muted, skeletons become invisible. Add bg-border to restore contrast:
<div className="bg-accent p-4">
<Skeleton className="h-4 w-24 bg-border" />
</div>
Apply bg-border when the parent has bg-accent, bg-muted, or bg-secondary.
Button, Link, a, and any onClick/href.'use client' unless layout depends on runtime values.alt, src, target, rel, title.Use descriptive labels: avatar, title, subtitle, description, card, transaction list, metrics row, badge/chip, action button. Prefer one comment per logical block rather than commenting every single <Skeleton>.
*-skeleton.tsx.import { Skeleton } from '@/shared/components/ui/skeleton'
import { cn } from '@/shared/lib/utils'
Use skeleton components as Suspense fallbacks:
<Suspense fallback={<InfoCardSkeleton />}>
<InfoCard />
</Suspense>
For Next.js route loading, add loading.tsx next to page.tsx. The loading UI must mirror the full page structure — not just one section.
Prefer (same structure as the page):
// loading.tsx — mirrors header + metrics + body sections
import { PageContent } from '@/shared/components/page-containers'
import { Skeleton } from '@/shared/components/ui/skeleton'
export default function Loading() {
return (
<PageContent className="mt-6 gap-6">
{/* header: icon + title + chips + description */}
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<Skeleton className="h-14 w-14 shrink-0" />
<div className="flex min-w-0 flex-col gap-2">
<Skeleton className="h-5.5 w-56" />
<div className="flex flex-wrap gap-2">
<Skeleton className="h-6 w-24" />
<Skeleton className="h-6 w-24" />
</div>
</div>
</div>
</div>
{/* body content */}
<div className="flex flex-col gap-2">
<Skeleton className="h-5.5 w-28" />
<div className="flex flex-col gap-1">
<Skeleton className="h-5 w-full" />
<Skeleton className="h-5 w-full" />
<Skeleton className="h-5 w-full max-w-4/5" />
</div>
</div>
</PageContent>
)
}
aria-* labels unless there is a specific accessibility requirement.aria-busy="true" on the parent container, not on each skeleton line.Before finishing, verify:
sm:, md:, lg:, xl:) are preservedbg-border where needed){component-name}-skeleton.tsx and placed next to the source componentnpx claudepluginhub yasielcabrera/addg-guidelines-skills --plugin addgProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.