mdxui

Product as Card

How Products render as cards, lists, and items - ProductCard, ProductList, ProductItem

Product as Card

A Product can render as a card component within lists, grids, catalogs, and directories. Cards provide compact representations optimized for browsing, comparison, and selection.


ProductCard

The ProductCard component renders a Product as a standalone card with image, title, description, pricing, and actions.

Props

interface ProductCardProps {
  /** Product to render */
  product: string | Product
  /** Card variant/style */
  variant?: 'default' | 'compact' | 'detailed' | 'minimal'
  /** Card orientation */
  orientation?: 'vertical' | 'horizontal'
  /** Show product image */
  showImage?: boolean
  /** Show pricing */
  showPricing?: boolean
  /** Show features */
  showFeatures?: boolean
  /** Show categories/tags */
  showCategories?: boolean
  /** Action button configuration */
  action?: {
    label: string
    href?: string
    onClick?: () => void
  }
  /** Custom className */
  className?: string
  /** Hover effects */
  hoverable?: boolean
  /** Clickable card */
  clickable?: boolean
  /** Selected state */
  selected?: boolean
}

Usage

import { ProductCard } from '@mdxui/beacon'

// Basic product card
<ProductCard product={product} />

// Compact variant
<ProductCard
  product={product}
  variant="compact"
  showImage={false}
/>

// Detailed card with features
<ProductCard
  product={product}
  variant="detailed"
  showPricing={true}
  showFeatures={true}
  showCategories={true}
  action={{
    label: 'Learn More',
    href: `/products/${product.id}`,
  }}
/>

// Horizontal layout
<ProductCard
  product={product}
  orientation="horizontal"
  hoverable={true}
/>

Card Variants

Default Variant

Standard card with image, title, description, and CTA:

<ProductCard
  product={apiProduct}
  variant="default"
  action={{ label: 'Get Started' }}
/>

Renders:

┌─────────────────────────────┐
│                             │
│      [Product Image]        │
│                             │
├─────────────────────────────┤
│ Product Name                │
│                             │
│ Brief description of the    │
│ product and its value...    │
│                             │
│ [Get Started →]             │
└─────────────────────────────┘

Compact Variant

Minimal card for dense layouts:

<ProductCard
  product={product}
  variant="compact"
  showImage={false}
/>

Renders:

┌─────────────────────────────┐
│ Product Name        [Icon]  │
│ Short description here      │
└─────────────────────────────┘

Detailed Variant

Full information card with pricing and features:

<ProductCard
  product={saasProduct}
  variant="detailed"
  showPricing={true}
  showFeatures={true}
  showCategories={true}
/>

Renders:

┌─────────────────────────────┐
│      [Product Image]        │
├─────────────────────────────┤
│ Product Name                │
│ #Category #Tag              │
│                             │
│ Detailed description of the │
│ product with more context   │
│                             │
│ Features:                   │
│ • Feature 1                 │
│ • Feature 2                 │
│ • Feature 3                 │
│                             │
│ From $19/month              │
│                             │
│ [Start Free Trial]          │
└─────────────────────────────┘

Minimal Variant

Text-only, ultra-compact:

<ProductCard
  product={product}
  variant="minimal"
  showImage={false}
  showPricing={false}
/>

Renders:

┌─────────────────────────────┐
│ Product Name                │
│ One-line description        │
└─────────────────────────────┘

Product Type Adaptations

Cards adapt their content based on product type:

SaaS Product Card

<ProductCard product={saasProduct} variant="detailed" />

Shows:

  • Product name and logo
  • "SaaS" badge
  • Description
  • Starting price (e.g., "$19/month")
  • Key features (limited to 3-5)
  • "Start Free Trial" CTA

API Product Card

<ProductCard product={apiProduct} variant="detailed" />

Shows:

  • Product name and icon
  • "API" badge
  • Description
  • Pricing (e.g., "$0.001/request")
  • API type (REST, GraphQL, etc.)
  • "Get API Key" CTA

Data Product Card

<ProductCard product={dataProduct} variant="detailed" />

Shows:

  • Product name and icon
  • "Data" badge
  • Description
  • Dataset size/records
  • Update frequency
  • "Browse Datasets" CTA

Headless Product Card

<ProductCard product={headlessProduct} variant="detailed" />

Shows:

  • Product name and icon
  • "Headless" badge
  • Description
  • Supported protocols (MCP, REST)
  • Usage pricing
  • "View API Docs" CTA

ProductList

The ProductList component renders multiple Products as a list, grid, or table.

Props

interface ProductListProps {
  /** Products to display */
  products: Array<string | Product>
  /** Layout mode */
  layout?: 'grid' | 'list' | 'table' | 'masonry'
  /** Card variant for grid/list */
  cardVariant?: 'default' | 'compact' | 'detailed' | 'minimal'
  /** Grid columns (for grid layout) */
  columns?: number | { sm?: number; md?: number; lg?: number }
  /** Filter configuration */
  filters?: {
    byType?: boolean
    byCategory?: boolean
    byPricing?: boolean
    custom?: Array<{
      id: string
      label: string
      options: Array<{ value: string; label: string }>
    }>
  }
  /** Sorting options */
  sort?: {
    by: 'name' | 'price' | 'created' | 'popularity'
    direction: 'asc' | 'desc'
  }
  /** Pagination */
  pagination?: {
    pageSize?: number
    currentPage?: number
    total?: number
  }
  /** Search configuration */
  searchable?: boolean
  /** Loading state */
  loading?: boolean
  /** Empty state */
  emptyState?: {
    title?: string
    description?: string
    action?: { label: string; onClick: () => void }
  }
  /** Custom className */
  className?: string
}

Usage

import { ProductList } from '@mdxui/beacon'

// Grid of products
<ProductList
  products={products}
  layout="grid"
  columns={{ sm: 1, md: 2, lg: 3 }}
  cardVariant="default"
/>

// List with filters
<ProductList
  products={products}
  layout="list"
  filters={{
    byType: true,
    byCategory: true,
  }}
  searchable={true}
/>

// Table view
<ProductList
  products={products}
  layout="table"
  sort={{
    by: 'name',
    direction: 'asc',
  }}
  pagination={{
    pageSize: 20,
    currentPage: 1,
  }}
/>

// Compact masonry layout
<ProductList
  products={products}
  layout="masonry"
  columns={4}
  cardVariant="compact"
/>

Layout Examples

Grid Layout

<ProductList
  products={products}
  layout="grid"
  columns={{ sm: 1, md: 2, lg: 3 }}
  cardVariant="default"
  searchable={true}
  filters={{
    byType: true,
    byCategory: true,
  }}
/>

Renders:

[Search: _____________] [Filters ▾]

┌─────────┐ ┌─────────┐ ┌─────────┐
│ Product │ │ Product │ │ Product │
│   #1    │ │   #2    │ │   #3    │
└─────────┘ └─────────┘ └─────────┘

┌─────────┐ ┌─────────┐ ┌─────────┐
│ Product │ │ Product │ │ Product │
│   #4    │ │   #5    │ │   #6    │
└─────────┘ └─────────┘ └─────────┘

List Layout

<ProductList
  products={products}
  layout="list"
  cardVariant="horizontal"
/>

Renders:

┌────────────────────────────────────┐
│ [Img] Product #1                   │
│       Description... [Action →]    │
└────────────────────────────────────┘

┌────────────────────────────────────┐
│ [Img] Product #2                   │
│       Description... [Action →]    │
└────────────────────────────────────┘

┌────────────────────────────────────┐
│ [Img] Product #3                   │
│       Description... [Action →]    │
└────────────────────────────────────┘

Table Layout

<ProductList
  products={products}
  layout="table"
  sort={{ by: 'name', direction: 'asc' }}
/>

Renders:

┌──────────────┬──────┬───────────┬────────────┐
│ Name ↑       │ Type │ Pricing   │ Status     │
├──────────────┼──────┼───────────┼────────────┤
│ Product A    │ SaaS │ $19/month │ Active     │
│ Product B    │ API  │ $0.001/req│ Active     │
│ Product C    │ Data │ $99/month │ Beta       │
└──────────────┴──────┴───────────┴────────────┘

Filtering and Sorting

<ProductList
  products={products}
  layout="grid"
  filters={{
    byType: true,
    byCategory: true,
    byPricing: true,
    custom: [
      {
        id: 'status',
        label: 'Status',
        options: [
          { value: 'active', label: 'Active' },
          { value: 'beta', label: 'Beta' },
        ],
      },
    ],
  }}
  sort={{
    by: 'popularity',
    direction: 'desc',
  }}
  searchable={true}
/>

Pagination

<ProductList
  products={products}
  pagination={{
    pageSize: 12,
    currentPage: 1,
    total: 48,
  }}
/>

Renders pagination controls:

[< Previous] [1] [2] [3] [4] [Next >]
Showing 1-12 of 48 products

ProductItem

The ProductItem component renders a Product as a single item within a list or table row.

Props

interface ProductItemProps {
  /** Product to render */
  product: string | Product
  /** Item variant */
  variant?: 'row' | 'inline' | 'badge'
  /** Show product image/icon */
  showImage?: boolean
  /** Show type badge */
  showType?: boolean
  /** Show pricing */
  showPricing?: boolean
  /** Show status */
  showStatus?: boolean
  /** Action configuration */
  action?: {
    label?: string
    icon?: string
    onClick?: () => void
  }
  /** Custom className */
  className?: string
  /** Selectable item */
  selectable?: boolean
  /** Selected state */
  selected?: boolean
  /** Disabled state */
  disabled?: boolean
}

Usage

import { ProductItem } from '@mdxui/beacon'

// Table row item
<ProductItem
  product={product}
  variant="row"
  showType={true}
  showPricing={true}
  action={{ icon: 'ExternalLink', onClick: () => {} }}
/>

// Inline mention
<ProductItem
  product={product}
  variant="inline"
  showImage={true}
/>

// Badge style
<ProductItem
  product={product}
  variant="badge"
  showType={false}
/>

Item Variants

Row Variant

For table rows:

<ProductItem
  product={product}
  variant="row"
  showImage={true}
  showType={true}
  showPricing={true}
  showStatus={true}
/>

Renders:

┌────────────────────────────────────────────┐
│ [Icon] Product Name  SaaS  $19/mo  Active │
└────────────────────────────────────────────┘

Inline Variant

For inline text mentions:

<ProductItem
  product={product}
  variant="inline"
  showImage={true}
/>

Renders:

Using [Icon] Product Name for analytics...

Badge Variant

Compact badge style:

<ProductItem
  product={product}
  variant="badge"
/>

Renders:

[Product Name]

Auto-Wiring

Product card components automatically query product data:

// Queries products collection
<ProductCard product="prod_123" />

// Queries multiple products
<ProductList products={['prod_1', 'prod_2', 'prod_3']} />

Auto-wiring features:

  1. Lazy loading - Products loaded as needed
  2. Caching - Reduces duplicate queries
  3. Relationships - Loads related features, prices
  4. Images - Fetches product images/logos

MDXLD Usage

Products in MDXLD can reference cards:

---
$context: https://schema.org.ai
$type: Page
---

# Our Products

Browse our product catalog:

<ProductList
  products={[
    'https://acme.com/products/saas',
    'https://acme.com/products/api',
    'https://acme.com/products/data',
  ]}
  layout="grid"
  columns={3}
/>

## Featured Product

<ProductCard
  product="https://acme.com/products/api"
  variant="detailed"
  showFeatures={true}
/>

Examples

Product Catalog Grid

<ProductList
  products={products}
  layout="grid"
  columns={{ sm: 1, md: 2, lg: 3 }}
  cardVariant="default"
  searchable={true}
  filters={{
    byType: true,
    byCategory: true,
  }}
  sort={{
    by: 'popularity',
    direction: 'desc',
  }}
  pagination={{
    pageSize: 12,
  }}
/>

Comparison Table

<ProductList
  products={[saasProduct, apiProduct, dataProduct]}
  layout="table"
  sort={{ by: 'price', direction: 'asc' }}
/>
<div className="carousel">
  {relatedProducts.map(product => (
    <ProductCard
      key={product.id}
      product={product}
      variant="compact"
      hoverable={true}
    />
  ))}
</div>

Product Selector

<ProductList
  products={products}
  layout="list"
  cardVariant="minimal"
  selectable={true}
  onSelect={(product) => setSelectedProduct(product)}
/>

Pricing Comparison

<div className="pricing-comparison">
  <ProductCard product={basicProduct} variant="detailed" selected={tier === 'basic'} />
  <ProductCard product={proProduct} variant="detailed" selected={tier === 'pro'} />
  <ProductCard product={enterpriseProduct} variant="detailed" selected={tier === 'enterprise'} />
</div>

Next Steps

On this page