Noctis

Skeleton

A loading placeholder that mirrors the shape of the content it stands in for, so the layout doesn't jump when the real data arrives. Compose Skeleton.Box, Skeleton.Circle, and Skeleton.Text inside a Skeleton.Root — an accessible loading region — and the whole group shimmers as one.

Basic

A Skeleton.Root wraps the placeholders in an accessible role="status" region that announces "Loading" once. Drop a Skeleton.Text inside for a paragraph of lines.

Loading

Shapes

Three shapes cover most content: Skeleton.Box (a rectangle for images, cards, or thumbnails), Skeleton.Circle (an avatar or icon disc), and Skeleton.Line (a single text bar). Box and circle are sized by you — set style/className dimensions to match what they stand in for.

Text

Skeleton.Text renders a stack of line bars — lines sets how many (default 3). The last line is drawn shorter so the block reads as ragged prose, and the line height tracks the surrounding font size.

Variants

variant is the animation: a moving shimmer sweep (the default), a gentle pulse fade, or a static none. Set it on Skeleton.Root and every shape inside inherits it, or set it per shape. Every variant respects prefers-reduced-motion and falls back to a calm static fill.

shimmer
Loading
pulse
Loading
none
Loading

Custom line widths

Compose Skeleton.Line directly when you want per-line widths instead of the uniform Skeleton.Text block — a short heading line over full body lines, say. Each line still inherits the group's animation.

Loading

A media card

Mirror the real layout — a leading avatar disc beside a title and meta lines, with a banner box above — so the placeholder occupies the same space the loaded card will.

Loading article

Swapping in content

The skeleton stands in while data loads; once it's ready, unmount the whole group and render the real content in its place. Because Skeleton.Root is a live region, screen readers hear "Loading" when it mounts and the real content when it replaces it.

Loading profile

Accessibility

Skeleton.Root is the accessible loading region — a role="status" live region (implicitly aria-live="polite") marked aria-busy="true", carrying a visually-hidden "Loading" name so assistive tech announces the load once. Override that name with label (e.g. label="Loading profile"); it resolves through the locale catalog. The placeholder shapes are decorative (aria-hidden), so the loading state is conveyed once by the region, not repeated per shape.

When the data arrives, unmount the skeleton and render the real content — the polite live region then announces the update. A standalone shape used without a Skeleton.Root is purely decorative; wrap it in your own aria-busy region if it needs to announce.

Anatomy

Compose the placeholder from its parts. Each shape also works standalone (for example via Skeleton.Box.props(...) spread onto a foreign element).

  • Skeleton.Root — the accessible loading group; owns the variant shared to its shapes and announces the load.
  • Skeleton.Box — a rectangular placeholder. Fills its inline space; set its height to match the content.
  • Skeleton.Circle — a circular placeholder for an avatar or icon. Sized by you.
  • Skeleton.Text — a stack of Skeleton.Lines (the lines count); a paragraph placeholder.
  • Skeleton.Line — a single text-line bar, for per-line composition.

Every rendered part carries a data-slot (noctis-skeleton on the group, noctis-skeleton-box/-circle/-text/-line on the shapes) for host-side styling — pair it with the data-variant axis the shapes stamp, off which the precompiled skeleton.css keys each shimmer/pulse animation.

On surfaces

The same placeholder re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. The fill is the surface-adaptive well overlay, so it stays visible on every layer.

root
Loading
elevated
Loading
menu
Loading
sunken
Loading

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every skeleton in that region retunes — e.g. .list { --noctis-skeleton-shimmer-animation-duration: var(--noctis-duration-slow); } quickens the sweep beneath it. See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table. Expand a row for the full type and description.

Skeleton.Root

Prop

Skeleton.Box

Prop

Skeleton.Circle

Prop

Skeleton.Text

Prop

Skeleton.Line

Prop

AttributeDescription
data-slotThe rendered element's slot — the anchor `skeleton.css` styles.
data-variantThe animation style — `shimmer` (a moving sweep, the default) | `pulse` (a gentle fade) | `none` (static).