Xzero UI
Pro library

Skeleton morphPro

Loading skeletons that grow into the real content, block by block, instead of swapping.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/skeleton-morph
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/skeleton-morph

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { MorphBlock, SkeletonMorph } from "@/components/xzero/skeleton-morph/skeleton-morph";

export function ProfileCard({ user }: { user?: User }) {
  return (
    <SkeletonMorph loading={!user} className="card">
      <MorphBlock radius="circle" width={48} height={48}>
        <img src={user?.avatar} alt="" width={48} height={48} />
      </MorphBlock>
      <MorphBlock width={120} lines={1} lineHeight={20}><p style={{ lineHeight: "20px" }}>{user?.name}</p></MorphBlock>
      <MorphBlock lines={3} lineHeight={20}><p style={{ lineHeight: "20px" }}>{user?.bio}</p></MorphBlock>
    </SkeletonMorph>
  );
}

API reference

SkeletonMorph

A loading region whose skeleton blocks become the real content. It marks itself busy while loading and eases to the new height when blocks change size.

PropTypeDefaultDescription
loading (required)boolean–While true, blocks show their skeletons and the region is aria-busy.
children (required)ReactNode–The loaded layout, with each visible piece wrapped in a MorphBlock.
staggernumber0.04Seconds between blocks as they resolve in reading order.
loadingLabelstring"Loading"Status text read by screen readers while loading.
asElementType"div"The root element. Style it as the card so its border follows the eased height.
classNamestring–Extra class on the root.
styleCSSProperties–Inline styles on the root.

MorphBlock

One piece of the layout. It is a size-matched skeleton while loading; on resolve the placeholder stretches to the content's measured box and fades while the content sharpens in, in place.

PropTypeDefaultDescription
childrenReactNode–The loaded content. It is not rendered while loading.
widthnumber | string"100%"Skeleton width.
heightnumber | string12px, or the lines heightSkeleton height.
radiusnumber | string | "circle"6Skeleton corner radius. circle makes a round avatar placeholder.
linesnumber–Shows a text skeleton with this many lines, each a bar centred in its line box; the last of several is shorter. Use lines={1} for single line text.
lineHeightnumber20Line height of the text in px, so the skeleton is exactly as tall as the loaded text.
as"div" | "span" | "p" | "li" | "section" | "article" | "header" | "footer" | "h2" | "h3" | "h4""div"The block element.
classNamestring–Extra class on the block.
styleCSSProperties–Inline styles on the block.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in loaders

Guidance for AI tools

Skeleton morph: Loading skeletons that grow into the real content, block by block, instead of swapping. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components