Skip to content

Migrating from ghl-ui Skeleton to HighRise Skeleton

This guide helps you migrate from the legacy UISkeleton component to the new HLSkeleton component. The new component provides enhanced TypeScript support, improved accessibility, and better integration with the HighRise design system.

Component Implementation Changes

Import Changes

diff
- import { UISkeleton } from '@gohighlevel/ghl-ui'
+ import { HLSkeleton } from '@platform-ui/highrise'

Basic Usage Changes

diff
<!-- Old usage -->
- <UISkeleton />

<!-- New usage -->
+ <HLSkeleton id="loading-skeleton" text />

Props Changes

Required Props

ghl-ui PropHighRise PropNotes
-idNew required prop for accessibility

Modified Props

ghl-ui PropHighRise PropNotes
heightheightNo changes - default: '18px'
circle-Removed, use round prop instead
-roundNew prop for rounded corners (default: true)

Examples

Basic Text Skeleton

vue
<!-- Old -->
<template>
  <UISkeleton />
</template>

<!-- New -->
<template>
  <HLSkeleton id="text-skeleton" text />
</template>

<script setup>
import { HLSkeleton } from '@platform-ui/highrise'
</script>

Multiple Lines with Different Widths

vue
<template>
  <HLSpace :size="10" vertical>
    <HLSkeleton id="title" width="70%" height="24px" />
    <HLSkeleton id="line1" width="100%" height="16px" />
    <HLSkeleton id="line2" width="90%" height="16px" />
    <HLSkeleton id="line3" width="80%" height="16px" />
  </HLSpace>
</template>

<script setup>
import { HLSkeleton, HLSpace } from '@platform-ui/highrise'
</script>

Avatar/Circle Skeleton

vue
<!-- Old -->
<template>
  <UISkeleton :text="false" circle height="48px" width="48px" />
</template>

<!-- New -->
<template>
  <HLSkeleton id="avatar-skeleton" :text="false" round height="48px" width="48px" />
</template>

Card Loading State

vue
<template>
  <div class="card-skeleton">
    <!-- Header with avatar and text -->
    <div class="flex items-center mb-4">
      <HLSkeleton id="avatar" :text="false" round height="48px" width="48px" />
      <div class="ml-3 flex-1">
        <HLSkeleton id="title" height="20px" width="40%" />
        <HLSkeleton id="subtitle" height="16px" width="60%" style="margin-top: 8px" />
      </div>
    </div>

    <!-- Content area -->
    <HLSkeleton id="content" :repeat="3" />

    <!-- Image placeholder -->
    <HLSkeleton id="image" :text="false" height="200px" width="100%" style="margin: 16px 0" />

    <!-- Footer actions -->
    <div class="flex justify-between">
      <HLSkeleton id="action1" :text="false" height="36px" width="80px" />
      <HLSkeleton id="action2" :text="false" height="36px" width="80px" />
    </div>
  </div>
</template>

Table Loading State

vue
<template>
  <div class="table-skeleton">
    <!-- Table header -->
    <div class="flex mb-4 pb-2 border-b">
      <HLSkeleton id="header1" :text="false" height="24px" width="25%" />
      <HLSkeleton id="header2" :text="false" height="24px" width="25%" class="ml-2" />
      <HLSkeleton id="header3" :text="false" height="24px" width="25%" class="ml-2" />
      <HLSkeleton id="header4" :text="false" height="24px" width="25%" class="ml-2" />
    </div>

    <!-- Table rows -->
    <div v-for="i in 5" :key="i" class="flex py-3">
      <HLSkeleton :id="`cell1-${i}`" :text="false" height="20px" width="25%" />
      <HLSkeleton :id="`cell2-${i}`" :text="false" height="20px" width="25%" class="ml-2" />
      <HLSkeleton :id="`cell3-${i}`" :text="false" height="20px" width="25%" class="ml-2" />
      <HLSkeleton :id="`cell4-${i}`" :text="false" height="20px" width="25%" class="ml-2" />
    </div>
  </div>
</template>

Form Loading State

vue
<template>
  <div class="form-skeleton">
    <div class="mb-4">
      <HLSkeleton id="label1" :text="false" height="20px" width="120px" />
      <HLSkeleton id="input1" :text="false" height="40px" width="100%" style="margin-top: 8px" />
    </div>

    <div class="mb-4">
      <HLSkeleton id="label2" :text="false" height="20px" width="120px" />
      <HLSkeleton id="input2" :text="false" height="40px" width="100%" style="margin-top: 8px" />
    </div>

    <div class="mt-6">
      <HLSkeleton id="submit" :text="false" height="44px" width="120px" />
    </div>
  </div>
</template>

Breaking Changes

  1. Required ID Prop:

    • The id prop is now required for accessibility
    • Must be unique within the page context
  2. Circle Prop Removed:

    • The circle prop has been replaced with round
    • Use round prop for both circular and rounded rectangle skeletons
  3. Default Values:

    • Default height is now '18px'
    • Default width is now '100%'
    • Text skeletons are rounded by default
  4. Styling Changes:

    • New CSS variable system
    • Different animation implementation
    • Modified border radius handling

Best Practices

  1. Accessibility:

    • Use meaningful id values
    • Match skeleton dimensions with actual content
    • Consider screen reader users
  2. Performance:

    • Use appropriate repeat values
    • Group related skeletons
    • Consider lazy loading
  3. User Experience:

    • Match skeleton layout with actual content
    • Use consistent animations
    • Consider mobile viewports
  4. Styling:

    • Use consistent dimensions
    • Follow design system guidelines
    • Consider dark mode

Common Patterns

List Item Loading

vue
<template>
  <div class="list-item-skeleton">
    <HLSkeleton id="list-title" width="60%" height="24px" />
    <HLSkeleton id="list-desc" width="90%" height="16px" :repeat="2" />
  </div>
</template>

Button Loading

vue
<template>
  <HLSkeleton id="button-skeleton" :text="false" width="120px" height="40px" round />
</template>

Image Loading

vue
<template>
  <HLSkeleton id="image-skeleton" :text="false" width="300px" height="200px" round />
</template>