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 productsProductItem
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:
- Lazy loading - Products loaded as needed
- Caching - Reduces duplicate queries
- Relationships - Loads related features, prices
- 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' }}
/>Related Products Carousel
<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
- Product as App - Rendering products as full applications
- Product as Site - Rendering products as marketing sites
- Product Contexts - Products in Web, API, and MCP contexts