For both search and product listing pages, you need to set up your product card component.

We call the product data that you receive for each product card that you have to render display. That component will receive a display of the type YourDisplay | null. YourDisplay is a type definition of your specific display. Please ask Depict for this.

If display is null, it means that there’s no data for this product card yet, and you should display a product card as close to the dimensions as the one you’ll display when you’ll have data, we’ll call this a “placeholder”. The placeholder serves as a loading indicator for users as well as enabling scroll restoration when going back and minimizing content shift.

The productCard component has to return a HTMLElement or HTMLElement[].

Example expected output of your product card component

`display` is `null`

`display` is `HoudiniDisplay`

Provided Placeholder components

You can use the ImagePlaceholder component to display a placeholder image while the product image is loading. You can use the TextPlaceholder component to display a placeholder text while the product title or price is loading.

Read the reference for more information.

Displaying color swatches

export interface YourDisplay {
  * The index of the variant to show in the variant_displays array
  variant_index: number;
  * All variants for that product - here you can, for example, get the color of each variant to display color swatches
  variant_displays: YourVariantDisplay[];
  // … other properties

Code example

You probably have an existing product card which you just can add placeholder functionality for. Here’s an example of how it could look like:

“Why is this JSX? I’m not using react!” - Did you miss the previous page?
import { ImagePlaceholder, TextPlaceholder } from "@depict-ai/js-ui";

export function ProductCard({ display }: { display: null | YourDisplay }) {
  const variant_to_show = display?.variant_displays[display?.variant_index];

  return [
      href={variant_to_show?.page_url || "#"}
      {...(variant_to_show && "recommendation_id" in variant_to_show
        ? { "data-recommendation-id": variant_to_show.recommendation_id }
        : {})}
      {variant_to_show ? (
        <div class="image-container">
          {/* Use the first image in image_urls as the default image */}
          <img class="default-image" src={variant_to_show.image_urls[0]} />
          {/* Use the second image in image_urls as the hover image */}
          <img class="hover-image" src={variant_to_show.image_urls[1]} />
      ) : (
        <ImagePlaceholder aspectRatio={imgAspectRatio} />

      <div class="text-container">
        <div class="rec-title">
          {variant_to_show.title ?? <TextPlaceholder height="1em" width="20ch" />}
        <div class="price-container">
          <span class="price">
            {variant_to_show ? (
              <FormatPrice price={variant_to_show.sale_price} />
            ) : (
              <TextPlaceholder height="1em" width="5ch" />
Note how we branch off to the shimmering placeholder effect in place of the content, when there is no content