商品詳細ブロック
ViewProductコンポーネントは、TypeScriptで構築された完全にカスタマイズ可能な商品表示コンポーネントです。組織情報、商品画像、チップ、タグ、セクション、モダンなデザインパターンを備えたカスタマイズ可能なアクションを含む商品詳細の表示のための完全なインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-view-product-block@0.1.4
📖 使用方法
import {ViewProduct} from '@nodeblocks/frontend-view-product-block';
- 基本的な使用方法
- 高度な使用方法
function BasicViewProduct() {
const chips = [
{ label: '新着' },
{ label: '注目商品' }
];
const tags = [
{ icon: 'star', label: 'プレミアム' },
{ label: ['電子機器', 'モバイル'] }
];
const sections = [
{ icon: 'info', label: 'モデル', value: 'iPhone 15 Pro' },
{ icon: 'attach_money', label: '価格', value: '¥149,800' },
{ label: '在庫状況', value: '在庫あり' }
];
const actions = [
{ label: 'カートに追加', onClick: () => console.log('カートに追加されました') },
{ label: '今すぐ購入', onClick: () => console.log('今すぐ購入がクリックされました') }
];
return (
<ViewProduct
organizationName="テックストア"
organizationBannerLink="#organization/techstore"
organizationLogoUrl="/img/icon.png"
imageUrl="/img/undraw_docusaurus_react.svg"
imageAlt="iPhone 15 Pro"
chips={chips}
headerTitle="iPhone 15 Pro - 最新モデル"
tags={tags}
sections={sections}
actions={actions}
style={{backgroundColor: 'white', padding: '16px'}}>
<ViewProduct.Header>
<ViewProduct.CompanyName />
<ViewProduct.Image />
<ViewProduct.Chips />
<ViewProduct.Title />
</ViewProduct.Header>
<ViewProduct.Content />
<ViewProduct.Actions />
</ViewProduct>
);
}
function AdvancedViewProduct() {
const chips = [
{ label: '🔥 ベストセラー' },
{ label: '⚡ 高速配送' },
{ label: '🎯 限定版' }
];
const tags = [
{ icon: 'star', label: '⭐ 4.9 プレミアム評価' },
{ icon: 'verified', label: ['🛡️ 認定済み', '🔒 安全', '💎 プレミアム'] }
];
const sections = [
{ icon: 'info', label: '📱 モデル', value: 'MacBook Pro 16" M3 Max' },
{ icon: 'attach_money', label: '💰 価格', value: '¥548,800' },
{ icon: 'inventory', label: '📦 在庫', value: '在庫あり - 残り12個' },
{ icon: 'local_shipping', label: '🚚 配送', value: '翌日無料配送' },
{ icon: 'support_agent', label: '🛠️ 保証', value: '3年間 AppleCare+' }
];
const actions = [
{ label: '🛒 カートに追加', onClick: () => console.log('カートに追加されました') },
{ label: '⚡ 今すぐ購入', onClick: () => console.log('今すぐ購入がクリックされました') },
{ label: '💝 ウィッシュリストに追加', onClick: () => console.log('ウィッシュリストに追加されました') }
];
return (
<ViewProduct
organizationName="🍎 Apple Store プレミアム"
organizationBannerLink="#apple-store"
organizationLogoUrl="/img/icon.png"
imageUrl="/img/undraw_docusaurus_react.svg"
imageAlt="MacBook Pro 16 M3 Max"
chips={chips}
headerTitle="💻 MacBook Pro 16 究極のパフォーマンス"
tags={tags}
sections={sections}
actions={actions}
style={{backgroundColor: '#f8f9fa', padding: '24px', borderRadius: '16px'}}>
{({ defaultBlocks, defaultBlockOrder }) => ({
blocks: {
...defaultBlocks,
// プレミアムグラデーションとガラス効果で強化されたヘッダー
header: {
...defaultBlocks.header,
props: {
...defaultBlocks.header.props,
style: {
...defaultBlocks.header.props?.style,
background: 'linear-gradient(145deg, #ffffff 0%, #f8fafc 100%)',
backdropFilter: 'blur(20px)',
borderRadius: '24px',
padding: '40px',
color: 'white',
marginBottom: '32px',
boxShadow: '0 25px 50px rgba(99, 102, 241, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.1)',
border: '1px solid rgba(255, 255, 255, 0.2)',
position: 'relative',
overflow: 'hidden'
}
}
},
// セクションプロパティを使用したカスタムコンテンツオーバーライド
content: {
...defaultBlocks.content,
props: {
...defaultBlocks.content.props,
children: (
<div style={{
background: 'linear-gradient(145deg, #ffffff 0%, #f8fafc 100%)',
borderRadius: '20px',
padding: '24px',
marginBottom: '32px',
boxShadow: '0 10px 30px rgba(0, 0, 0, 0.08)',
border: '1px solid rgba(226, 232, 240, 0.8)'
}}>
{/* 強化されたセクション表示 */}
<h3 style={{
fontSize: '18px',
fontWeight: '700',
color: '#1e293b',
marginBottom: '20px',
margin: '0 0 20px 0'
}}>
📋 商品詳細
</h3>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: '16px',
marginBottom: '24px'
}}>
{sections.map((section, index) => (
<div key={index} style={{
background: 'white',
borderRadius: '12px',
padding: '16px',
boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)',
border: '1px solid rgba(226, 232, 240, 0.8)',
display: 'flex',
alignItems: 'center',
gap: '12px'
}}>
<div style={{
width: '40px',
height: '40px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '10px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '18px',
color: 'white'
}}>
{section.icon ? '📌' : '•'}
</div>
<div>
<p style={{
fontSize: '12px',
color: '#64748b',
margin: '0 0 4px 0'
}}>
{section.label}
</p>
<p style={{
fontSize: '14px',
fontWeight: '600',
color: '#1e293b',
margin: 0
}}>
{section.value}
</p>
</div>
</div>
))}
</div>
{/* カスタマーレビュー */}
<div style={{
background: 'linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%)',
borderRadius: '12px',
padding: '20px'
}}>
<div style={{
display: 'flex',
alignItems: 'center',
gap: '12px',
marginBottom: '12px'
}}>
<div style={{
width: '40px',
height: '40px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: '16px',
fontWeight: '600'
}}>
田
</div>
<div>
<p style={{
fontSize: '14px',
fontWeight: '600',
color: '#1e293b',
margin: '0 0 4px 0'
}}>
田中花子
</p>
<div style={{ display: 'flex', gap: '2px' }}>
{Array.from({ length: 5 }, (_, i) => (
<span key={i} style={{ color: '#fbbf24', fontSize: '12px' }}>⭐</span>
))}
</div>
</div>
</div>
<p style={{
fontSize: '14px',
color: '#64748b',
lineHeight: '1.5',
margin: 0,
fontStyle: 'italic'
}}>
"動画編集にとって信じられないパフォーマンスです。M3 Maxチップは8K映像を楽々処理します!"
</p>
</div>
</div>
)
}
},
// モダンなボタンスタイリングとホバー効果で強化されたアクション
actions: {
...defaultBlocks.actions,
props: {
...defaultBlocks.actions.props,
style: {
...defaultBlocks.actions.props?.style,
background: 'linear-gradient(145deg, #ffffff 0%, #f8fafc 100%)',
borderRadius: '20px',
padding: '32px',
textAlign: 'center',
boxShadow: '0 20px 40px rgba(102, 126, 234, 0.25)',
border: '1px solid rgba(255, 255, 255, 0.2)',
position: 'relative',
overflow: 'hidden'
}
}
}
},
blockOrder: defaultBlockOrder
})}
</ViewProduct>
);
}
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
organizationName | string | undefined | 商品を販売する組織の名前 |
organizationBannerLink | string | undefined | 組織バナーのリンクURL |
organizationLogoUrl | string | undefined | 組織ロゴ画像のURL |
imageUrl | string | 必須 | メイン商品画像のソースURL |
imageAlt | string | undefined | 商品画像のaltテキスト |
chips | Array<{label: string}> | 必須 | 表示するチップラベルの配列 |
headerTitle | string | 必須 | 商品のメインタイトルテキスト |
tags | Array<{icon?: IconType, label: string | string[]}> | 必須 | オプションアイコン付きタグの配列 |
sections | Array<{icon?: IconType, label: string, value: string}> | 必須 | 情報セクションの配列 |
actions | Array<{label: ReactNode, onClick: () => void}> | undefined | アクションボタンの配列 |
className | string | undefined | コンテナスタイリング用の追加CSSクラス名 |
children | BlocksOverride | undefined | デフォルトレンダリングをオーバーライドするカスタムブロックコンポーネント |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
サブコンポーネント
ViewProductコンポーネントは、異なるセクション用の複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
ViewProduct.CompanyName
組織名をヘッディングとして表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストから | デフォルト会社名をオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Image
メイン商品画像を表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
imageUrl | string | コンテキストから | 商品画像のソースURL |
imageAlt | string | コンテキストから | 商品画像のaltテキスト |
children | ReactNode | コンテキストから | デフォルト画像をオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Chips
商品チップを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
chips | Array<{label: string}> | コンテキストから | 表示するチップの配列 |
children | ReactNode | コンテキストから | デフォルトチップをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Title
商品タイトルをヘッディングとして表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストから | デフォルトタイトルをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Header
会社名、画像、チップ、タイトルを含む商品ヘッダーのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
organizationName | string | コンテキストから | ヘッダー用の組織名 |
organizationLogo | string | コンテキストから | 組織ロゴURL |
organizationBannerLink | string | コンテキストから | 組織バナーリンク |
imageUrl | string | コンテキストから | 商品画像URL |
imageAlt | string | コンテキストから | 商品画像altテキスト |
chips | Array<{label: string}> | コンテキストから | チップの配列 |
headerTitle | string | コンテキストから | 商品タイトル |
children | ReactNode | コンテキストから | デフォルトヘッダーコンテンツをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Sections
複数の情報セクションを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
sections | Array<{icon?: IconType, label: string, value: string}> | コンテキストから | 表示するセクションの配列 |
children | ReactNode | コンテキストから | デフォルトセクションをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Tags
商品タグを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tags | Array<{icon?: IconType, label: string | string[]}> | コンテキストから | 表示するタグの配列 |
children | ReactNode | コンテキストから | デフォルトタグをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.CompanyBanner
組織のクリック可能なバナーを表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
companyName | ReactNode | コンテキストから | 表示する会社名 |
link | string | コンテキストから | バナーリンクのURL |
icon | enum | undefined | バナー用のオプションアイコン |
logo | string | コンテキストから | バナー用のロゴURL |
children | ReactNode | コンテキストから | デフォルトバナーをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML a 要素プロパティを継承します。
ViewProduct.Content
タグ、セクション、会社バナーを含むメイン商品コンテンツのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tags | Array<{icon?: IconType, label: string | string[]}> | コンテキストから | タグの配列 |
sections | Array<{icon?: IconType, label: string, value: string}> | コンテキストから | セクションの配列 |
organizationName | string | コンテキストから | 組織名 |
organizationBannerLink | string | コンテキストから | 組織バナーリンク |
organizationLogoUrl | string | コンテキストから | 組織ロゴURL |
children | ReactNode | コンテキストから | デフォルトコンテンツをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
ViewProduct.Actions
アクションボタンのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
actions | Array<{label: ReactNode, onClick: () => void}> | コンテキストから | アクションボタンの配列 |
children | ReactNode | コンテキストから | デフォルトアクションをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのHTML div 要素プロパティを継承します。
🔧 TypeScript サポート
包括的な型定義による完全なTypeScriptサポート:
import ViewProduct from '@nodeblocks/frontend-view-product-block';
import { ReactNode } from 'react';
interface ProductChip {
label: string;
}
interface ProductTag {
icon?: IconType;
label: string | string[];
}
interface ProductSection {
icon?: IconType;
label: string;
value: string;
}
interface ProductAction {
label: ReactNode;
onClick: () => void;
}
interface ViewProductProps {
organizationName?: string;
organizationBannerLink?: string;
organizationLogoUrl?: string;
imageUrl: string;
imageAlt?: string;
chips: ProductChip[];
headerTitle: string;
tags: ProductTag[];
sections: ProductSection[];
actions?: ProductAction[];
className?: string;
children?: ReactNode;
}
interface CustomProductData {
id: string;
name: string;
price: number;
category: string;
brand: string;
availability: 'in-stock' | 'out-of-stock' | 'pre-order';
rating: number;
features: string[];
specifications: {
[key: string]: string;
};
}
const ProductDetailsView = () => {
const productData: CustomProductData = {
id: 'PROD-2024-001',
name: 'プレミアムワイヤレスヘッドホン',
price: 29999,
category: '電子機器',
brand: 'AudioTech',
availability: 'in-stock',
rating: 4.8,
features: ['ノイズキャンセリング', 'Bluetooth 5.0', '急速充電'],
specifications: {
'バッテリー持続時間': '30時間',
'ドライバーサイズ': '40mm',
'重量': '250g'
}
};
const chips: ProductChip[] = [
{ label: 'ベストセラー' },
{ label: '送料無料' }
];
const tags: ProductTag[] = [
{ icon: 'star', label: `${productData.rating} 評価` },
{ label: productData.features }
];
const sections: ProductSection[] = [
{ icon: 'info', label: 'ブランド', value: productData.brand },
{ icon: 'category', label: 'カテゴリ', value: productData.category },
{ icon: 'attach_money', label: '価格', value: `¥${productData.price.toLocaleString()}` },
{ icon: 'inventory', label: '在庫状況', value: productData.availability },
...Object.entries(productData.specifications).map(([key, value]) => ({
label: key,
value: value
}))
];
const actions: ProductAction[] = [
{
label: 'カートに追加',
onClick: () => console.log(`${productData.name} をカートに追加しました`)
},
{
label: '今すぐ購入',
onClick: () => console.log(`${productData.name} を購入中`)
}
];
return (
<ViewProduct
organizationName="AudioTech ストア"
organizationBannerLink="/brands/audiotech"
organizationLogoUrl="/audiotech-logo.png"
imageUrl="/headphones-image.jpg"
imageAlt={productData.name}
chips={chips}
headerTitle={productData.name}
tags={tags}
sections={sections}
actions={actions}
className="custom-product-view">
<ViewProduct.Header />
<ViewProduct.Content />
<ViewProduct.Actions />
</ViewProduct>
);
};
// TypeScriptを使用したカスタムコンポーネントオーバーライド
const CustomProductView = () => {
const customChips: ProductChip[] = [
{ label: '限定版' },
{ label: '24時間配送' }
];
const customTags: ProductTag[] = [
{ icon: 'local_fire_department', label: 'ホットディール' },
{ icon: 'verified', label: ['認定済み', '保証付き'] }
];
const customSections: ProductSection[] = [
{ icon: 'timer', label: '配送時間', value: '24時間' },
{ icon: 'local_shipping', label: '配送', value: '無料' },
{
icon: 'support_agent',
label: 'サポート',
value: '24時間365日カスタマーサービス'
}
];
return (
<ViewProduct
organizationName="プレミアム電子機器"
headerTitle="限定ゲーミングヘッドセット"
imageUrl="/gaming-headset.jpg"
chips={customChips}
tags={customTags}
sections={customSections}>
<ViewProduct.Header className="custom-header">
<ViewProduct.CompanyName />
<div className="custom-image-container">
<ViewProduct.Image />
</div>
<ViewProduct.Chips />
<ViewProduct.Title />
</ViewProduct.Header>
<ViewProduct.Content>
<div className="custom-content-layout">
<ViewProduct.Tags />
<ViewProduct.Sections />
<ViewProduct.CompanyBanner />
</div>
</ViewProduct.Content>
<ViewProduct.Actions />
</ViewProduct>
);
};
モダンなウェブ標準を使用して❤️で構築されました。