migration wip
This commit is contained in:
402
components/content/ContentComponentsExample.tsx
Normal file
402
components/content/ContentComponentsExample.tsx
Normal file
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
* Content Components Example
|
||||
* Demonstrates how to use the content components with WordPress data
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Hero,
|
||||
Section,
|
||||
SectionHeader,
|
||||
SectionContent,
|
||||
SectionGrid,
|
||||
FeaturedImage,
|
||||
ContentRenderer,
|
||||
Breadcrumbs,
|
||||
ContentBlock,
|
||||
RichText,
|
||||
Avatar,
|
||||
ImageGallery,
|
||||
} from './index';
|
||||
import { Button, Card, CardHeader, CardBody, CardFooter, Grid } from '../ui';
|
||||
import { Page, Post, Product, getMediaById } from '../../lib/data';
|
||||
|
||||
// Example: Hero component with WordPress data
|
||||
export const ExampleHero: React.FC<{
|
||||
page: Page;
|
||||
}> = ({ page }) => {
|
||||
const featuredMedia = page.featuredImage ? getMediaById(page.featuredImage) : null;
|
||||
|
||||
return (
|
||||
<Hero
|
||||
title={page.title}
|
||||
subtitle={page.excerptHtml ? page.excerptHtml.replace(/<[^>]*>/g, '') : undefined}
|
||||
backgroundImage={featuredMedia?.localPath}
|
||||
backgroundAlt={featuredMedia?.alt || page.title}
|
||||
height="lg"
|
||||
variant="dark"
|
||||
overlay={true}
|
||||
overlayOpacity={0.6}
|
||||
ctaText="Learn More"
|
||||
ctaLink="#content"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Section component for content blocks
|
||||
export const ExampleSection: React.FC<{
|
||||
title: string;
|
||||
content: string;
|
||||
background?: 'default' | 'light' | 'dark';
|
||||
}> = ({ title, content, background = 'default' }) => {
|
||||
return (
|
||||
<Section background={background} padding="xl">
|
||||
<SectionHeader title={title} align="center" />
|
||||
<SectionContent>
|
||||
<ContentRenderer content={content} />
|
||||
</SectionContent>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Featured content grid
|
||||
export const ExampleContentGrid: React.FC<{
|
||||
posts: Post[];
|
||||
}> = ({ posts }) => {
|
||||
return (
|
||||
<Section background="light" padding="xl">
|
||||
<SectionHeader
|
||||
title="Latest News"
|
||||
subtitle="Stay updated with our latest developments"
|
||||
align="center"
|
||||
/>
|
||||
<SectionGrid cols={3} gap="md">
|
||||
{posts.map((post) => {
|
||||
const featuredMedia = post.featuredImage ? getMediaById(post.featuredImage) : null;
|
||||
return (
|
||||
<Card key={post.id} variant="elevated">
|
||||
{featuredMedia && (
|
||||
<div className="relative h-48">
|
||||
<FeaturedImage
|
||||
src={featuredMedia.localPath}
|
||||
alt={featuredMedia.alt || post.title}
|
||||
size="full"
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<CardHeader>
|
||||
<h3 className="text-xl font-bold">{post.title}</h3>
|
||||
<small className="text-gray-500">
|
||||
{new Date(post.datePublished).toLocaleDateString()}
|
||||
</small>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<RichText
|
||||
html={post.excerptHtml}
|
||||
className="text-gray-600 line-clamp-3"
|
||||
/>
|
||||
</CardBody>
|
||||
<CardFooter>
|
||||
<Button variant="primary" size="sm">
|
||||
Read More
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</SectionGrid>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Product showcase
|
||||
export const ExampleProductShowcase: React.FC<{
|
||||
product: Product;
|
||||
}> = ({ product }) => {
|
||||
const images = product.images.map((img) => ({
|
||||
src: img,
|
||||
alt: product.name,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Section padding="xl">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Product Images */}
|
||||
<div>
|
||||
{product.featuredImage && (
|
||||
<FeaturedImage
|
||||
src={product.featuredImage}
|
||||
alt={product.name}
|
||||
size="full"
|
||||
aspectRatio="4:3"
|
||||
priority
|
||||
/>
|
||||
)}
|
||||
{images.length > 1 && (
|
||||
<div className="mt-4">
|
||||
<ImageGallery images={images.slice(1)} cols={3} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl md:text-4xl font-bold mb-2">{product.name}</h1>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-2xl font-bold text-primary">
|
||||
{product.regularPrice} {product.currency}
|
||||
</span>
|
||||
{product.salePrice && (
|
||||
<span className="text-lg text-gray-500 line-through">
|
||||
{product.salePrice} {product.currency}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RichText html={product.descriptionHtml} />
|
||||
|
||||
{product.categories.length > 0 && (
|
||||
<div>
|
||||
<strong>Categories:</strong>
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
{product.categories.map((cat) => (
|
||||
<span key={cat.id} className="px-3 py-1 bg-gray-100 rounded-full text-sm">
|
||||
{cat.name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex gap-3">
|
||||
<Button variant="primary" size="lg">
|
||||
Add to Cart
|
||||
</Button>
|
||||
<Button variant="outline" size="lg">
|
||||
Contact Sales
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Breadcrumbs with WordPress page structure
|
||||
export const ExampleBreadcrumbs: React.FC<{
|
||||
page: Page;
|
||||
ancestors?: Page[];
|
||||
}> = ({ page, ancestors = [] }) => {
|
||||
const items = [
|
||||
...ancestors.map((p) => ({
|
||||
label: p.title,
|
||||
href: `/${p.locale}${p.path}`,
|
||||
})),
|
||||
{
|
||||
label: page.title,
|
||||
},
|
||||
];
|
||||
|
||||
return <Breadcrumbs items={items} />;
|
||||
};
|
||||
|
||||
// Example: Full page layout with all components
|
||||
export const ExamplePageLayout: React.FC<{
|
||||
page: Page;
|
||||
relatedPosts?: Post[];
|
||||
}> = ({ page, relatedPosts = [] }) => {
|
||||
const featuredMedia = page.featuredImage ? getMediaById(page.featuredImage) : null;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* Hero Section */}
|
||||
<Hero
|
||||
title={page.title}
|
||||
subtitle={page.excerptHtml ? page.excerptHtml.replace(/<[^>]*>/g, '') : undefined}
|
||||
backgroundImage={featuredMedia?.localPath}
|
||||
backgroundAlt={featuredMedia?.alt || page.title}
|
||||
height="md"
|
||||
variant="dark"
|
||||
overlay
|
||||
overlayOpacity={0.5}
|
||||
/>
|
||||
|
||||
{/* Breadcrumbs */}
|
||||
<Breadcrumbs
|
||||
items={[
|
||||
{ label: 'Home', href: '/' },
|
||||
{ label: page.title },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Main Content */}
|
||||
<Section padding="xl">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<ContentRenderer content={page.contentHtml} />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Related Posts */}
|
||||
{relatedPosts.length > 0 && (
|
||||
<Section background="light" padding="xl">
|
||||
<SectionHeader title="Related Content" align="center" />
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{relatedPosts.map((post) => (
|
||||
<Card key={post.id} variant="bordered">
|
||||
<CardBody>
|
||||
<h3 className="text-lg font-bold mb-2">{post.title}</h3>
|
||||
<RichText
|
||||
html={post.excerptHtml}
|
||||
className="text-gray-600 text-sm line-clamp-2"
|
||||
/>
|
||||
</CardBody>
|
||||
<CardFooter>
|
||||
<Button variant="ghost" size="sm">
|
||||
Read More
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
)}
|
||||
|
||||
{/* CTA Section */}
|
||||
<Section background="primary" padding="xl">
|
||||
<div className="text-center text-white">
|
||||
<h2 className="text-3xl font-bold mb-4">Ready to Get Started?</h2>
|
||||
<p className="text-xl mb-6 opacity-90">
|
||||
Contact us today for more information about our products and services.
|
||||
</p>
|
||||
<div className="flex justify-center gap-3">
|
||||
<Button variant="secondary" size="lg">
|
||||
Contact Us
|
||||
</Button>
|
||||
<Button variant="ghost" size="lg" className="text-white border-white hover:bg-white/10">
|
||||
View Products
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Blog post layout
|
||||
export const ExampleBlogPost: React.FC<{
|
||||
post: Post;
|
||||
author?: {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
};
|
||||
}> = ({ post, author }) => {
|
||||
const featuredMedia = post.featuredImage ? getMediaById(post.featuredImage) : null;
|
||||
|
||||
return (
|
||||
<article className="max-w-4xl mx-auto">
|
||||
{/* Header */}
|
||||
<header className="mb-8 text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-4">{post.title}</h1>
|
||||
<div className="flex items-center justify-center gap-4 text-gray-600">
|
||||
<time dateTime={post.datePublished}>
|
||||
{new Date(post.datePublished).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</time>
|
||||
{author && (
|
||||
<div className="flex items-center gap-2">
|
||||
{author.avatar && <Avatar src={author.avatar} alt={author.name} size="sm" />}
|
||||
<span>{author.name}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Featured Image */}
|
||||
{featuredMedia && (
|
||||
<div className="mb-8">
|
||||
<FeaturedImage
|
||||
src={featuredMedia.localPath}
|
||||
alt={featuredMedia.alt || post.title}
|
||||
size="full"
|
||||
aspectRatio="16:9"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Content */}
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<ContentRenderer content={post.contentHtml} />
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
||||
// Example: Product category grid
|
||||
export const ExampleProductGrid: React.FC<{
|
||||
products: Product[];
|
||||
category?: string;
|
||||
}> = ({ products, category }) => {
|
||||
return (
|
||||
<Section padding="xl">
|
||||
<SectionHeader
|
||||
title={category ? `${category} Products` : 'Our Products'}
|
||||
subtitle="Explore our range of high-quality products"
|
||||
align="center"
|
||||
/>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{products.map((product) => {
|
||||
const image = product.featuredImage || product.images[0];
|
||||
return (
|
||||
<Card key={product.id} variant="elevated" className="flex flex-col">
|
||||
{image && (
|
||||
<div className="relative">
|
||||
<FeaturedImage
|
||||
src={image}
|
||||
alt={product.name}
|
||||
size="full"
|
||||
aspectRatio="4:3"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<CardHeader>
|
||||
<h3 className="text-lg font-bold">{product.name}</h3>
|
||||
<div className="text-primary font-semibold text-lg">
|
||||
{product.regularPrice} {product.currency}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<RichText
|
||||
html={product.shortDescriptionHtml}
|
||||
className="text-gray-600 text-sm line-clamp-2"
|
||||
/>
|
||||
</CardBody>
|
||||
<CardFooter className="mt-auto">
|
||||
<Button variant="primary" size="sm" fullWidth>
|
||||
View Details
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
ExampleHero,
|
||||
ExampleSection,
|
||||
ExampleContentGrid,
|
||||
ExampleProductShowcase,
|
||||
ExampleBreadcrumbs,
|
||||
ExamplePageLayout,
|
||||
ExampleBlogPost,
|
||||
ExampleProductGrid,
|
||||
};
|
||||
Reference in New Issue
Block a user