Klarhimmel UI

Skeleton

Stable

A pulsing placeholder for content that is on its way. It stops pulsing when motion is reduced.

npx shadcn add @klarhimmel/skeleton

When to use

  • Use for

    Content that loads in a moment, shaped like what will replace it.

  • Not for

    Long jobs. Show progress and say what is happening.

  • Pairs with

    Card, lists, SkeletonText for paragraphs.

Preview

skeleton.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Skeleton, SkeletonText } from '@/components/klarhimmel/ui/skeleton';

export default function Example() {
  return (
    <Theme theme="brand">
      <Skeleton className="h-6 w-1/2" />
      <SkeletonText lines={3} label="Loading the review" />
    </Theme>
  );
}

Install

Import

import { Skeleton, SkeletonText } from '@/components/klarhimmel/ui/skeleton';
Lands in
components/klarhimmel/ui/skeleton.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
Render in
Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.

Examples

  • List

    Loading bookings

    import { Skeleton } from '@/components/klarhimmel/ui/skeleton';
    
    export default function SkeletonList() {
      return (
        <div className="flex w-full max-w-md flex-col gap-3">
          <p role="status" className="text-kh-small text-kh-muted">Loading bookings</p>
          <ul aria-hidden className="flex flex-col gap-3">
            {[0, 1, 2, 3].map((i) => (
              <li key={i} className="flex items-center gap-3">
                <Skeleton className="size-10 shrink-0 rounded-kh-pill" />
                <div className="flex min-w-0 flex-1 flex-col gap-2">
                  <Skeleton className="h-4 w-2/5" />
                  <Skeleton className="h-3 w-4/5" />
                </div>
              </li>
            ))}
          </ul>
        </div>
      );
    }
  • Text

    import { Skeleton, SkeletonText } from '@/components/klarhimmel/ui/skeleton';
    
    export default function SkeletonTextDemo() {
      return (
        <div className="flex w-full max-w-md flex-col gap-4">
          <p aria-hidden className="text-kh-small text-kh-muted">Loading the review</p>
          <Skeleton className="h-6 w-1/2" />
          <SkeletonText lines={4} label="Loading the review" />
        </div>
      );
    }

API reference

PropTypeDefaultDescription
classNamestring-Size it with width and height classes (Skeleton).
linesnumber3Number of lines; the last is shorter (SkeletonText).
labelstring'Loading'What is announced once for the group (SkeletonText).

Accessibility

KeyDoes
TabSkips it: a skeleton is not interactive
Screen readerA single block is hidden. SkeletonText announces its label once, as a status

Not interactive. Give the group a visible or spoken label (SkeletonText label) and do not leave skeletons on screen for long.

Accessibility