๐ŸŸข Skeleton


Basic

NSkeleton is a placeholder while the content is being loaded.

<template>
  <div class="w-250px flex flex-col space-y-3">
    <NSkeleton
      class="h-125px"
    />
    <div class="space-y-2">
      <NSkeleton class="h-4" />
      <NSkeleton class="h-4 w-80%" />
    </div>
  </div>
</template>

Shape

rounded="{value}" - change the shape of the skeleton.

๐Ÿš€ You can freely adjust the size of the rounded using any value imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size or states such as hover:lg, focus:3xl to change size based on input state and more.

The value determines the overall form of the skeleton. You can always add and customize it using utility classes in the class attribute.
<script setup lang="ts">
const shapes = [
  'rounded-lg',
  'rounded-full',
  'rounded-l-full',
  'rounded-tr-4xl',
  'rounded-bl-1cm',
  'rounded-r-3xl',
  'rounded-b-full',
  'rounded-lb-full',
]
</script>

<template>
  <div class="flex flex-col space-y-4">
    <div class="flex items-center space-x-4">
      <NSkeleton
        rounded="0 md:full"
        class="h-12 w-12"
      />
      <div class="space-y-2">
        <NSkeleton class="h-4 w-[250px]" />
        <NSkeleton class="h-4 w-[200px]" />
      </div>
    </div>

    <NSkeleton class="h-6" />

    <div class="flex flex-wrap gap-4">
      <NSkeleton
        v-for="(shape, i) in shapes"
        :key="i"
        class="h-24 w-24"
        :class="shape"
      />
    </div>
  </div>
</template>

Color

skeleton="{color}" - change the color of the skeleton.

You can use any color provided by the Tailwind CSS color palette, the default is gray. You can also add your own colors to the palette through the Configuration section.
<template>
  <div class="w-250px">
    <div class="flex items-end space-x-2">
      <NSkeleton
        rounded="b-full"
        class="h-15 w-15"
      />

      <div class="space-y-2">
        <NSkeleton
          skeleton="primary"
          rounded="t-full"
          class="h-15 w-15"
        />
        <NSkeleton
          rounded="l-full"
          class="h-15 w-15"
        />
      </div>
    </div>
  </div>
</template>

Props

import type { HTMLAttributes } from 'vue'

interface Extensions { class?: HTMLAttributes['class'] }

export interface NSkeletonProps extends Extensions {
  /**
   * Allows you to add `UnaUI` skeleton preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/skeleton.ts
   * @example
   * skeleton="green""
   */
  skeleton?: string
  /**
   * Allows you to change the size of the skeleton.
   *
   * @default base|md
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/skeleton.ts
   */
  una?: {
    // base
    skeleton?: HTMLAttributes['class']
  }
}

Presets

import { parseColor } from '@unocss/preset-mini/utils'
import type { Theme } from '@unocss/preset-uno'
import type { RuleContext } from '@unocss/core'

type SkeletonPrefix = 'skeleton'

export const staticSkeleton: Record<`${SkeletonPrefix}-${string}` | SkeletonPrefix, string> = {
  // base
  skeleton: 'skeleton-gray text-md animate-pulse rounded-md w-full h-0.5em bg-brand',
}

export const dynamicSkeleton = [
  [/^skeleton-(.*)$/, ([, body]: string[], { theme }: RuleContext<Theme>) => {
    const color = parseColor(body, theme)
    if ((color?.cssColor?.type === 'rgb' || color?.cssColor?.type === 'rgba') && color.cssColor.components)
      return `n-${body}-100 dark:n-${body}-800`
  }],
]

export const skeleton = [
  ...dynamicSkeleton,
  staticSkeleton,
]

Component

<script setup lang="ts">
import type { NSkeletonProps } from '../../types'
import { cn } from '../../utils'

const props = defineProps<NSkeletonProps>()
</script>

<template>
  <div
    :class="
      cn(
        'skeleton',
        props.class,
        props.una?.skeleton,
      )
    "
    :skeleton="props.skeleton"
    :size="props.size"
  >
    <slot />
  </div>
</template>