Basic Usage

Wrap a component, bind a loading flag, done.

Basic Usage

Wrap and toggle

The core pattern is a single <Skeletonizer> wrapper bound to your loading state:

<script setup lang="ts">
const { data: user, pending } = await useLazyFetch('/api/user')
</script>

<template>
  <Skeletonizer :enabled="pending">
    <article class="profile">
      <img :src="user?.avatar" width="64" height="64" class="avatar">
      <h1>{{ user?.name }}</h1>
      <p>{{ user?.bio }}</p>
      <button>Follow</button>
    </article>
  </Skeletonizer>
</template>

While pending is true, the avatar, heading, paragraph and button render as animated bones. When the fetch resolves, the originals are restored instantly — in the same place, with no layout shift.

Global control

From anywhere in your app, drive the global skeleton state:

const skeletonizer = useSkeletonizer()
skeletonizer.enable()
skeletonizer.disable()
skeletonizer.toggle()

Any <Skeletonizer> without an explicit :enabled prop follows this global flag.

Manual primitives

Prefer to author a skeleton by hand (e.g. for content not yet rendered)? Use the building blocks:

<template>
  <SkeletonList :items="6" :lines="2" />
  <SkeletonTable :rows="10" :columns="5" />
  <SkeletonCard media avatar :lines="3" />
</template>

See Components for the full list.