Product

ProductCard

Displays a product with image, price, discount badge, and quick-action buttons.

ProductCard

The CProductCard is the primary component for displaying products in grids, carousels, and listings. It renders a product image with optional discount badge, hover overlay with quick-add/wishlist actions, and a body with title, rating, and price.

Preview
Premium Wireless Headphones -20%

Premium Wireless Headphones

4.7(128)
$199.99249.99 USD

Usage

<template>
  <CProductCard
    :product="product"
    show-quick-add
    show-wishlist
    show-rating
    @add-to-cart="handleAddToCart"
    @toggle-wishlist="handleWishlist"
  />
</template>

Minimal

<CProductCard :product="product" />

With Variants

<!-- Soft variant, large size -->
<CProductCard :product="product" variant="soft" size="lg" />

<!-- Ghost variant, small size -->
<CProductCard :product="product" variant="ghost" size="sm" />

Custom Image Aspect Ratio

<CProductCard :product="product" image-aspect="aspect-[3/4]" />

Props

PropTypeDefaultDescription
productProductrequiredProduct data from @commercejs/types
variant'outline' | 'soft' | 'ghost''outline'Visual style variant
size'sm' | 'md' | 'lg''md'Size of the card
showQuickAddbooleanfalseShow "Add to Cart" button on hover
showWishlistbooleanfalseShow wishlist toggle on hover
showRatingbooleanfalseShow star rating if available
imageAspectstring'aspect-square'CSS aspect ratio class for image
asanyRender root as a different component
uiPartial<{...}>Per-instance theme overrides

Events

EventPayloadDescription
add-to-cartProductEmitted when quick-add button is clicked
toggle-wishlistProductEmitted when wishlist button is clicked

Slots

SlotScoped PropsDescription
image{ product, image }Custom image rendering
badge{ discount, hasDiscount }Discount badge overlay
actions{ product }Hover overlay actions
title{ name }Product title text
rating{ rating }Star rating display
price{ price }Price display

Example: Custom Price Slot

<CProductCard :product="product">
  <template #price="{ price }">
    <div class="flex items-center gap-2">
      <span class="text-primary font-bold">{{ price.formatted }}</span>
      <UBadge color="success" size="xs">Free Shipping</UBadge>
    </div>
  </template>
</CProductCard>

Theme

Override via app.config.ts under ui.productCard:

export default defineAppConfig({
  ui: {
    productCard: {
      slots: {
        root: 'rounded-xl ring ring-default bg-default overflow-hidden hover:shadow-lg transition-shadow',
        imageWrapper: 'relative overflow-hidden bg-elevated',
        body: 'p-3 space-y-1.5',
        title: 'font-medium text-sm text-highlighted line-clamp-2',
        price: 'font-semibold text-highlighted',
        originalPrice: 'text-sm line-through text-muted',
      },
      variants: {
        size: {
          sm: { body: 'p-2 space-y-1', title: 'text-xs' },
          lg: { body: 'p-4 space-y-2', title: 'text-base' },
        },
      },
    },
  },
})

Or per-instance:

<CProductCard
  :product="product"
  :ui="{ root: 'shadow-xl', title: 'text-lg' }"
/>