Sophic Interface Systems
Components

Skeleton

Pulse bars that stand in for content while a value is fetching.

Pulse bars

Money-weighted

Time-weighted

Placeholder bars for unknown values. Known labels stay as text. The fill is bg-skeleton so the pulse reads on cards and tinted drawers — not --muted, which disappeared on light.

You might be looking for:

  • Shimmer

    Animated text highlight while copy is generating.

  • Page Loading

    Full-viewport wait — mark only, no content bars.

How we compose them

Start from the loaded layout and swap only what you do not know yet. Do not invent a second structure, a spinner, or a generic pulse block that ignores the frame.

Keep the same shell, gaps, and row heights. If a title or caption is already known, render it as text and pulse the value. When the loaded UI is a shared component, use its *Skeleton sibling so loading and loaded cannot drift — those pages document the extra props (known title, row count, plot silhouette). One-off screens compose Skeleton bars by hand with h-* / w-*. Do not use Page Loading for in-page content.

Fill is always bg-skeleton. Do not hardcode bg-muted or bg-neutral-* on bars.

Usage

import { Skeleton } from "@sophic/portal-ui/components/ui/skeleton";
import {
  ItemListSkeleton,
  SectionCard,
  StatMetricCardSkeleton,
} from "@sophic/portal-ui";

<Skeleton className="h-7 w-40" />

<StatMetricCardSkeleton title="Money-weighted" subtitle />

<SectionCard title="Pending orders">
  <ItemListSkeleton rows={3} />
</SectionCard>

Props

Skeleton also accepts every native <div> attribute.

Prop

Type

Default

Changelog

  • 2 September 2026 — Pulse uses --skeleton (bg-skeleton) instead of --muted. Holding return tiles pulse an All-time subtitle row. Full notes

On this page