preskok/ui

Async Image

Compound async image with lazy loading, skeleton placeholder, and error fallback.

Installation

pnpm dlx @preskok-org/ui@latest add async-image

Usage

Basic usage with default loading skeleton and error fallback:

import { AsyncImage } from "@/registry/preskok/ui/preskok-ui/async-image"
 
export function AsyncImageExample() {
  return (
    <AsyncImage.Root
      src="https://example.com/image.jpg"
      alt="Description"
      width={300}
      height={200}
    />
  )
}

With custom slots:

<AsyncImage.Root
  src="/photo.jpg"
  alt="Photo"
  width={400}
  height={300}
>
  <AsyncImage.Loading className="flex items-center justify-center bg-muted">
    <span>Loading…</span>
  </AsyncImage.Loading>
  <AsyncImage.Error>Failed to load image</AsyncImage.Error>
</AsyncImage.Root>

Disable lazy loading (load immediately):

<AsyncImage.Root
  src="/hero.jpg"
  alt="Hero"
  width={800}
  height={400}
  lazyLoad={false}
/>

Props

AsyncImage.Root

PropTypeDefaultDescription
srcstringImage URL. Empty string triggers error state.
altstring""Accessible alt text for the image.
widthnumber | stringWidth of the container and image.
heightnumber | stringHeight of the container and image.
imgPropsOmit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "width" | "height">Props passed to the underlying <img> when loaded.
loadingDelayMsnumber0Optional delay in ms before transitioning from loading to loaded (e.g. to avoid flicker).
lazyLoadfalse | IntersectionObserverInit{ threshold: 0.01, rootMargin: "75%" }Lazy load when in view. Set to false to load immediately.
onLoadingEnd() => voidCalled when the image has loaded successfully.
onErrorFallback() => voidCalled when the image fails to load.
childrenReact.ReactNodeOptional compound slots: AsyncImage.Loading, AsyncImage.Error, AsyncImage.Content.

All other div props (e.g. className, style) are forwarded to the root container.

Slots

  • AsyncImage.Loading — Rendered while status === "loading". Default: skeleton placeholder.
  • AsyncImage.Error — Rendered when status === "error". Default: icon + "Image unavailable".
  • AsyncImage.Content — Rendered when status === "loaded". Default: the <img> element. Override to customize the loaded image element.