Feedback

Skeleton

A placeholder shape shown while real content is loading, so layout doesn’t jump when it arrives.

Copy
<template>
  <div class="flex w-full max-w-xs items-center gap-3">
    <JSkeleton shape="circle" />
    <JSkeleton shape="text" :lines="2" width="100%" />
  </div>
</template>

Installation #

With the Nuxt module, every component is auto-imported — there is nothing to add. In a plain Vue project, import what you use:

Copy
import { JSkeleton } from '@juxtui/ui'

Usage #

Copy
<JSkeleton shape="circle" />
<JSkeleton shape="text" :lines="3" />

Size a skeleton to match the content it stands in for — give it the same width and height (or wrap it) so nothing shifts once the real content mounts.

The pulse is a slow breath, not a shimmer, and turns off entirely under prefers-reduced-motion.

Variants & examples #

Shapes#

Rect for blocks of media, circle for avatars, text for lines of copy.

Copy
<template>
  <div class="flex flex-col gap-4">
    <JSkeleton width="12rem" height="6rem" />
    <JSkeleton shape="circle" />
    <JSkeleton shape="text" :lines="3" width="16rem" />
  </div>
</template>

Loading state of a card#

Copy
<template>
  <div class="flex w-full max-w-xs flex-col gap-3 rounded-lg border border-border p-4">
    <div class="flex items-center gap-3">
      <JSkeleton shape="circle" />
      <JSkeleton shape="text" width="8rem" />
    </div>
    <JSkeleton shape="text" :lines="3" />
  </div>
</template>

API #

Props

PropTypeDefault Description
shape'rect' | 'text' | 'circle''rect'text renders one or more lines; circle suits avatars.
linesnumber1Number of lines for text. The last one is shorter, like a real paragraph.
widthstring—Any CSS length, e.g. 12rem or 100%.
heightstring—Any CSS length. For text, sets the height of each line.

Accessibility #

  • Marked aria-hidden="true" — it stands in for content that isn’t there yet, so it has nothing to announce.
  • Announce the loading state itself separately, e.g. with an aria-live region or a nearby JSpinner with a label.