motif svelteArc

Skeleton ported

Reserve space while content is still loading.

Reserve space while content is still loading.

Live specimen

Loading demo…

Guidance

When to use

  • Loading states for content whose shape is known, like a profile or comment.
  • Swapping a placeholder into real content with a crossfade and height spring.

When not to use

  • Use progress when you can report a percentage.
  • Use empty-state when loading finished and there is nothing to show.
  • Use text-shimmer for an AI thinking or status line.

Installation

pnpm dlx shadcn-svelte@latest add @arcui/skeleton

Usage

<script lang="ts">
  import { Skeleton } from '$lib/components/skeleton';
</script>

<Skeleton avatar lines={2} loading={!user}>
      {user && <ProfileCard user={user} />}
    </Skeleton>

Variants & Examples

With content

Placeholder crossfades into children while loading is true. Phase 1 swaps to the settled layer.

<Skeleton avatar lines={3} loading={loading}>
  <Profile />
</Skeleton>

Standalone

No children. lines is clamped to 1–6, so lines={9} renders six bars.

<Skeleton lines={4} />

API Reference

PropTypeDefaultDescription
labelstring"Loading content"aria-label of the loading status.
linesnumber3Number of text lines, clamped to 1-6.
avatarbooleanfalseAdds a round avatar placeholder.
childrenSnippet–Content to reveal once loading finishes. With children the placeholder crossfades into them.
loadingbooleantrueKeeps the placeholder visible while true. Only used with children.
classNamestring–Class on the outer element.

Keyboard Interactions

KeyAction
NoneThe placeholder is not in the tab order. Its shapes are aria-hidden.

Accessibility

  • The placeholder is role="status" with aria-busy and an aria-label; its shapes are aria-hidden.
  • With children, the wrapper sets aria-busy while loading.

Motion

Phase 1: the CSS pulse runs (1.8s, 90ms stagger on --index, 11 iterations) and a loading toggle shows the settled layer immediately. Phase 2: the placeholder fades out, content rises 4px, and the height springs from placeholder to content. Reduced motion stops the pulse and skips the height animation.

Notes for AI

  • Use while fetching content whose shape is known. Use progress when you can report a percentage, and empty-state when there is nothing to show.
  • Wrap the real content as children and drive loading to get the crossfade; without children it renders only the placeholder.

Source of truth: registry/components/skeleton/skeleton.tsx