oneie
Version:
Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.
474 lines (390 loc) • 12.5 kB
Markdown
---
title: Integration Example
dimension: things
category: docs
tags: ai
scope: global
created: 2025-11-03
updated: 2025-11-03
version: 1.0.0
ai_context: |
This document is part of the things dimension in the docs category.
Location: one/things/docs/ecommerce/INTEGRATION-EXAMPLE.md
Purpose: Documents product page conversion elements - integration examples
For AI agents: Read this to understand INTEGRATION EXAMPLE.
---
# Product Page Conversion Elements - Integration Examples
## Quick Integration Guide
### 1. Product Listing Page (Already Integrated)
The QuickViewModal is already integrated into ProductCard.tsx. No additional work needed.
```tsx
// ProductCard.tsx already includes:
import { QuickViewModal } from "./QuickViewModal";
// At the end of component:
<QuickViewModal
product={product}
open={showQuickView}
onOpenChange={setShowQuickView}
/>;
```
### 2. Product Detail Page - Complete Example
Create or update your product detail page at `src/pages/ecommerce/product/[slug].astro`:
```astro
---
// src/pages/ecommerce/product/[slug].astro
import Layout from '@/layouts/Layout.astro';
import { ProductGallery } from '@/components/ecommerce/interactive/ProductGallery';
import { SizeGuideModal } from '@/components/ecommerce/interactive/SizeGuideModal';
import { StickyCartBar } from '@/components/ecommerce/interactive/StickyCartBar';
import { VariantSelector } from '@/components/ecommerce/interactive/VariantSelector';
import { QuantitySelector } from '@/components/ecommerce/interactive/QuantitySelector';
import { AddToCartButton } from '@/components/ecommerce/interactive/AddToCartButton';
// Fetch product data (example)
const { slug } = Astro.params;
const product = {
id: '1',
slug: 'premium-cotton-tshirt',
name: 'Premium Cotton T-Shirt',
description: 'Ultra-soft 100% organic cotton with a modern fit...',
price: 29.99,
compareAtPrice: 49.99,
images: [
'https://images.unsplash.com/photo-1521572163474-6864f9cf17ab',
'https://images.unsplash.com/photo-1503342217505-b0a15ec3261c',
'https://images.unsplash.com/photo-1618354691373-d851c5c3a990',
],
thumbnail: 'https://images.unsplash.com/photo-1521572163474-6864f9cf17ab',
category: 'Apparel',
tags: ['shirts', 'cotton', 'organic'],
variants: [
{
id: 'size',
name: 'Size',
type: 'size' as const,
options: [
{ value: 'xs', label: 'XS', inStock: true },
{ value: 's', label: 'S', inStock: true },
{ value: 'm', label: 'M', inStock: true },
{ value: 'l', label: 'L', inStock: false },
{ value: 'xl', label: 'XL', inStock: true },
],
},
{
id: 'color',
name: 'Color',
type: 'color' as const,
options: [
{ value: 'black', label: 'Black', inStock: true },
{ value: 'white', label: 'White', inStock: true },
{ value: 'navy', label: 'Navy', inStock: true },
],
},
],
inStock: true,
inventory: 47,
rating: 4.8,
reviewCount: 234,
featured: true,
createdAt: new Date('2024-01-15'),
updatedAt: new Date(),
};
---
<Layout title={product.name}>
<div class="container mx-auto px-4 py-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Left Column: Image Gallery -->
<div>
<ProductGallery
client:load
images={product.images}
productName={product.name}
/>
</div>
<!-- Right Column: Product Info -->
<div class="space-y-6">
<div>
<h1 class="text-3xl font-bold text-foreground">{product.name}</h1>
<p class="mt-2 text-muted-foreground">{product.description}</p>
</div>
<div class="flex items-baseline gap-3">
<span class="text-3xl font-bold text-foreground">
${product.price.toFixed(2)}
</span>
{product.compareAtPrice && (
<>
<span class="text-xl text-muted-foreground line-through">
${product.compareAtPrice.toFixed(2)}
</span>
<span class="text-sm font-bold text-destructive">
Save {Math.round(((product.compareAtPrice - product.price) / product.compareAtPrice) * 100)}%
</span>
</>
)}
</div>
<!-- Variant Selection Section (Important: Add id="variant-selector") -->
<div id="variant-selector" class="space-y-4">
{product.variants?.map((variant) => (
<div key={variant.id}>
<div class="flex items-center justify-between mb-2">
<label class="text-sm font-medium">{variant.name}</label>
{variant.type === 'size' && (
<button
class="text-sm text-primary hover:underline"
onclick="document.getElementById('size-guide-trigger')?.click()"
>
Size Guide
</button>
)}
</div>
<VariantSelector
client:load
variant={variant}
selectedValue=""
onSelect={(value) => console.log('Selected:', value)}
/>
</div>
))}
</div>
<div class="flex items-center gap-3">
<span class="text-sm font-medium">Quantity:</span>
<QuantitySelector
client:load
value={1}
onChange={(qty) => console.log('Quantity:', qty)}
max={product.inventory || 999}
/>
</div>
{product.inventory && product.inventory < 10 && (
<div class="text-sm text-orange-600 dark:text-orange-400 flex items-center gap-2">
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
Only {product.inventory} left in stock
</div>
)}
<AddToCartButton
client:load
productId={product.id}
productName={product.name}
productSlug={product.slug}
price={product.price}
image={product.thumbnail}
inStock={product.inStock}
/>
</div>
</div>
</div>
<!-- Size Guide Modal (Hidden trigger) -->
<button id="size-guide-trigger" class="hidden" />
<SizeGuideModal
client:load
open={false}
onOpenChange={(open) => console.log('Size guide:', open)}
productType="apparel"
/>
<!-- Sticky Cart Bar (Mobile) -->
<StickyCartBar
client:load
product={product}
selectedVariants={{}}
quantity={1}
triggerElementId="variant-selector"
/>
</Layout>
```
### 3. Size Guide Integration Options
#### Option A: Trigger from Link
```tsx
// In your component
const [showSizeGuide, setShowSizeGuide] = useState(false);
<button
onClick={() => setShowSizeGuide(true)}
className="text-sm text-primary hover:underline"
>
Size Guide
</button>
<SizeGuideModal
open={showSizeGuide}
onOpenChange={setShowSizeGuide}
productType="apparel"
/>
```
#### Option B: Global Size Guide Link
```astro
<!-- In your layout footer or header -->
<button id="size-guide-trigger" data-product-type="apparel">
Size Guide
</button>
<script>
document.getElementById('size-guide-trigger')?.addEventListener('click', () => {
// Trigger modal open
});
</script>
```
### 4. Sticky Cart Bar Requirements
**Important:** Add `id="variant-selector"` to the element you want to trigger the sticky bar:
```tsx
// Option 1: Wrap variant selectors
<div id="variant-selector" className="space-y-4">
{/* Variant selectors here */}
</div>
// Option 2: Add to specific element
<div className="variant-section">
<h3 id="variant-selector">Choose Options</h3>
{/* Variants */}
</div>
// Option 3: Custom trigger point
<StickyCartBar
product={product}
triggerElementId="custom-trigger-id"
/>
```
### 5. Responsive Behavior
All components are responsive by default:
- **Quick View**: 2-column on desktop, 1-column on mobile
- **Product Gallery**: Swipe gestures on mobile, mouse controls on desktop
- **Size Guide**: Scrollable tables on mobile
- **Sticky Cart Bar**: Mobile only (hidden on desktop with `md:hidden`)
### 6. Custom Styling
Override styles using Tailwind classes:
```tsx
// Example: Custom modal width
<DialogContent className="max-w-6xl">
{/* Content */}
</DialogContent>
// Example: Custom sticky bar position
<div className="fixed bottom-20 left-0 right-0">
<StickyCartBar {...props} />
</div>
```
### 7. Event Tracking
Add analytics to track user interactions:
```tsx
// Quick View Modal
const handleQuickView = () => {
setShowQuickView(true);
// Track event
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", "quick_view", {
product_id: product.id,
product_name: product.name,
});
}
};
// Size Guide
const handleSizeGuideOpen = () => {
setShowSizeGuide(true);
// Track event
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", "size_guide_open", {
product_type: "apparel",
});
}
};
// Sticky Cart Bar
<StickyCartBar
product={product}
onAddToCart={() => {
// Track conversion from sticky bar
window.gtag?.("event", "add_to_cart_sticky", {
product_id: product.id,
value: product.price,
});
}}
/>;
```
### 8. A/B Testing Setup
Test different trigger points and behaviors:
```tsx
// Example: Test scroll threshold
const stickyBarVariant = Math.random() > 0.5 ? "early" : "late";
<StickyCartBar
product={product}
triggerElementId={
stickyBarVariant === "early" ? "product-title" : "variant-selector"
}
/>;
```
### 9. Performance Optimization
```tsx
// Lazy load modals
import { lazy, Suspense } from "react";
const SizeGuideModal = lazy(() =>
import("./SizeGuideModal").then((m) => ({ default: m.SizeGuideModal })),
);
// Use with Suspense
<Suspense fallback={<div>Loading...</div>}>
<SizeGuideModal {...props} />
</Suspense>;
```
### 10. Error Handling
```tsx
// Add error boundaries
import { ErrorBoundary } from "@/components/ErrorBoundary";
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<ProductGallery images={product.images} productName={product.name} />
</ErrorBoundary>;
```
---
## Common Patterns
### Pattern 1: Product Card Grid with Quick View
```astro
---
const products = await fetchProducts();
---
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
{products.map(product => (
<ProductCard client:load product={product} />
))}
</div>
```
### Pattern 2: Product Detail with All Features
```astro
<!-- See complete example above in section 2 -->
```
### Pattern 3: Category Page with Filters
```astro
---
import { FilterSidebar } from '@/components/ecommerce/interactive/FilterSidebar';
import { ProductGrid } from '@/components/ecommerce/static/ProductGrid';
---
<div class="flex gap-6">
<aside class="w-64">
<FilterSidebar client:load />
</aside>
<main class="flex-1">
<ProductGrid client:load products={products} />
</main>
</div>
```
---
## Troubleshooting
### Quick View Not Opening
- Check that `showQuickView` state is managed correctly
- Verify `client:load` is added to ProductCard
- Check browser console for errors
### Sticky Bar Not Appearing
- Verify `id="variant-selector"` exists on trigger element
- Check that component has `client:load` directive
- Test on mobile device or resize browser window
- Ensure element is in the DOM before scroll
### Image Zoom Not Working
- Verify `client:load` on ProductGallery
- Check that images array is not empty
- Test click events in browser console
### Size Guide Table Overflow
- Add `overflow-x-auto` to table wrapper
- Reduce font size on mobile
- Consider horizontal scroll indicator
---
## Next Steps
1. Add these components to your product detail page
2. Test on multiple devices (mobile, tablet, desktop)
3. Track analytics events
4. A/B test different configurations
5. Monitor conversion rate improvements
Expected results based on industry benchmarks:
- 15-20% increase in add-to-cart rate (quick view)
- 25-30% reduction in returns (size guide)
- 10-15% increase in mobile conversions (sticky bar)
- 270% increase in conversions (high-quality images with zoom)