Ghostly
Reference

Components & Hooks

Complete API reference for all Ghostly React components and hooks.

<Ghostly>

The primary component. Wraps any content to display skeleton loaders while data is loading.

import { Ghostly } from '@ghostly-ui/react'

Props

Prop

Type

Behavior

When loading={true}:

  • Sets data-ghostly="{animation}" on the wrapper element
  • Sets aria-busy="true" for screen readers
  • Sets CSS custom properties for radius, speed, color, and shine
  • All descendant text/media become skeleton blocks via CSS

When loading={false}:

  • Removes all skeleton attributes
  • Children render normally with zero overhead
  • If smooth is true, elements fade out gracefully

Examples

// Basic
<Ghostly loading={isLoading}>
  <UserCard user={data} />
</Ghostly>

// All options
<Ghostly
  loading={isLoading}
  animation="pulse"
  radius="lg"
  speed="fast"
  as="article"
  smooth
>
  <BlogPost post={data} />
</Ghostly>

// Custom colors via props (no CSS needed)
<Ghostly
  loading={true}
  color="hsl(260 30% 88%)"
  shine="hsl(260 30% 94%)"
>
  <HeroSection data={data} />
</Ghostly>

<GhostlyList>

Skeleton loader for lists and grids. Clones a template element N times during loading.

import { GhostlyList } from '@ghostly-ui/react'

Props

Prop

Type

Example

// Basic grid
<GhostlyList
  loading={isLoading}
  count={8}
  item={<ProductCard />}
  className="grid grid-cols-2 gap-4 md:grid-cols-4"
>
  {products?.map(p => <ProductCard key={p.id} product={p} />)}
</GhostlyList>

// Semantic list with custom colors
<GhostlyList
  loading={isLoading}
  count={5}
  item={<TodoItem />}
  as="ul"
  color="hsl(200 50% 85%)"
  className="space-y-2"
>
  {todos?.map(t => <TodoItem key={t.id} todo={t} />)}
</GhostlyList>

<GhostlySuspense>

Suspense-powered skeleton loader. Automatically shows a skeleton of your fallback component while children are suspended. No manual loading state needed.

import { GhostlySuspense } from '@ghostly-ui/react'

Props

Prop

Type

How it works

GhostlySuspense wraps React's <Suspense> and automatically:

  1. Renders your fallback component inside <Ghostly loading={true}> as the Suspense fallback
  2. When children resolve, shows them normally

This is the recommended approach for apps using React Server Components, use(), or any data-fetching library that integrates with Suspense.

Examples

// Basic — zero loading state management
<GhostlySuspense fallback={<ProductCard />}>
  <AsyncProductCard id={123} />
</GhostlySuspense>

// With options
<GhostlySuspense
  fallback={<UserProfile />}
  animation="pulse"
  radius="lg"
  smooth
  className="p-4"
>
  <AsyncUserProfile userId={456} />
</GhostlySuspense>

// Multiple boundaries
<div className="grid grid-cols-2 gap-6">
  <GhostlySuspense fallback={<Chart />} animation="shimmer">
    <AsyncChart />
  </GhostlySuspense>
  <GhostlySuspense fallback={<Feed />} animation="wave">
    <AsyncFeed />
  </GhostlySuspense>
</div>

<GhostlyProvider>

Sets default configuration for all Ghostly descendants. Nested providers inherit from their parent — only override what you specify.

import { GhostlyProvider } from '@ghostly-ui/react'

Props

Prop

Type

Priority: Instance props > Nearest GhostlyProvider > Parent GhostlyProvider > Built-in defaults

Nested providers

<GhostlyProvider animation="wave" radius="lg">
  {/* animation="wave", radius="lg", speed="normal" */}
  <GhostlyProvider speed="fast">
    {/* animation="wave" (inherited), radius="lg" (inherited), speed="fast" */}
    <App />
  </GhostlyProvider>
</GhostlyProvider>

useGhostly()

Hook to read the nearest Ghostly context and get spreadable skeleton props.

import { useGhostly } from '@ghostly-ui/react'

Return value

Prop

Type

getGhostlyProps()

Returns an object you can spread onto any HTML element to apply skeleton styles manually — useful for custom components that don't use <Ghostly>.

function CustomSkeleton() {
  const { loading, getGhostlyProps } = useGhostly()

  return (
    <div {...getGhostlyProps()}>
      <h2>Title placeholder</h2>
      <p>Description placeholder</p>
    </div>
  )
}

// Usage: inside a Ghostly or GhostlyProvider tree
<Ghostly loading={isLoading}>
  <CustomSkeleton />
</Ghostly>

The returned object contains:

  • data-ghostly — animation value (only when loading)
  • aria-busy — true (only when loading)
  • aria-live — "polite" (always)
  • style — CSS variables for radius and speed (only when loading)

Types

All types are exported from both @ghostly-ui/core and @ghostly-ui/react.

type GhostlyAnimation = 'shimmer' | 'pulse' | 'wave' | 'none'
type GhostlyRadius = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'full'
type GhostlySpeed = 'slow' | 'normal' | 'fast'

interface GhostlyConfig {
  animation?: GhostlyAnimation
  radius?: GhostlyRadius
  speed?: GhostlySpeed
  color?: string   // Custom skeleton base color
  shine?: string   // Custom shimmer highlight color
}

Radius values

PropCSS Output
none0px
xs2px
sm4px
md8px
lg12px
full9999px

Speed values

PropCSS Output
slow2s
normal1.5s
fast0.8s