商品詳細ブロック
ViewProductコンポーネントは、TypeScriptとMUIで構築された完全にカスタマイズ可能な商品表示コンポーネントです。組織情報、商品画像、チップ、タグ、セクション、モダンなデザインパターンを備えたカスタマイズ可能なアクションを含む商品詳細の表示のための完全なインターフェースを提供します。
🚀 インストール
npm install @nodeblocks/frontend-view-product-block@0.2.0
📖 使用法
import {ViewProduct} from '@nodeblocks/frontend-view-product-block';
- 基本的な使用法
- 高度な使用法
function BasicViewProduct() { const chips: ProductChip[] = [{label: '新着'}, {label: '注目商品'}]; const tags: ProductTag[] = [{label: 'プレミアム'}, {label: ['電子機器', 'モバイル']}]; const sections: ProductSection[] = [ {label: 'モデル', value: 'iPhone 15 Pro'}, {label: '価格', value: '¥149,800'}, {label: '在庫状況', value: '在庫あり'}, ]; const actions: ProductAction[] = [ {label: 'カートに追加', onClick: () => console.log('カートに追加されました')}, {label: '今すぐ購入', onClick: () => console.log('今すぐ購入がクリックされました')}, ]; return ( <ViewProduct organizationName="テックストア" imageUrl="/img/undraw_docusaurus_react.svg" imageAlt="iPhone 15 Pro" chips={chips} headerTitle="iPhone 15 Pro - 最新モデル" tags={tags} sections={sections} actions={actions} sx={{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: ProductChip[] = [{label: 'ベストセラー'}, {label: '高速配送'}, {label: '限定版'}]; const tags: ProductTag[] = [{label: '4.9 プレミアム評価'}, {label: ['認定済み', '安全', 'プレミアム']}]; const sections: ProductSection[] = [ {label: 'モデル', value: 'MacBook Pro 16" M3 Max'}, {label: '価格', value: '¥548,800'}, {label: '在庫', value: '在庫あり - 残り12個'}, {label: '配送', value: '翌日無料配送'}, {label: '保証', value: '3年間 AppleCare+'}, ]; const actions: ProductAction[] = [ {label: 'カートに追加', onClick: () => console.log('カートに追加されました')}, {label: '今すぐ購入', onClick: () => console.log('今すぐ購入がクリックされました')}, {label: 'ウィッシュリストに追加', onClick: () => console.log('ウィッシュリストに追加されました')}, ]; return ( <ViewProduct organizationName="Apple Store プレミアム" imageUrl="/img/undraw_docusaurus_react.svg" imageAlt="MacBook Pro 16 M3 Max" chips={chips} headerTitle="MacBook Pro 16 究極のパフォーマンス" tags={tags} sections={sections} actions={actions} sx={{ background: 'linear-gradient(145deg, #f8fafc 0%, #f1f5f9 100%)', borderRadius: '20px', border: '1px solid #e2e8f0', }} > {({defaultBlocks, defaultBlockOrder}) => ({ blocks: { ...defaultBlocks, // Enhanced header with slate gradient header: { ...defaultBlocks.header, props: { ...defaultBlocks.header.props, sx: { background: 'linear-gradient(135deg, #0f172a 0%, #1e293b 100%)', borderRadius: '16px', padding: '24px', color: 'white', marginBottom: '16px', boxShadow: '0 10px 25px rgba(0, 0, 0, 0.15)', }, }, }, // Enhanced content area content: { ...defaultBlocks.content, props: { ...defaultBlocks.content.props, children: ( <div style={{ background: 'white', borderRadius: '14px', padding: '24px', marginBottom: '16px', boxShadow: '0 4px 15px rgba(0, 0, 0, 0.08)', border: '1px solid #e2e8f0', }} > <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(200px, 1fr))', gap: '16px', marginBottom: '24px', }} > {sections.map((section, index) => ( <div key={index} style={{ background: '#f8fafc', borderRadius: '10px', padding: '16px', border: '1px solid #e2e8f0', display: 'flex', flexDirection: 'column', gap: '6px', }} > <span style={{ fontSize: '12px', color: '#64748b', fontWeight: '500', textTransform: 'uppercase', letterSpacing: '0.5px', }} > {section.label} </span> <span style={{ fontSize: '15px', fontWeight: '600', color: '#1e293b', }} > {section.value} </span> </div> ))} </div> {/* Tags display */} <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', }} > {tags.map((tag, index) => { const labelText = Array.isArray(tag.label) ? tag.label.join(' / ') : tag.label; return ( <span key={index} style={{ background: 'linear-gradient(135deg, #dbeafe 0%, #e0e7ff 100%)', color: '#1e40af', padding: '6px 14px', borderRadius: '20px', fontSize: '13px', fontWeight: '600', border: '1px solid #bfdbfe', }} > {labelText} </span> ); })} </div> </div> ), }, }, // Enhanced actions with modern button styling actions: { ...defaultBlocks.actions, props: { ...defaultBlocks.actions.props, sx: { background: 'linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)', borderRadius: '14px', padding: '20px', justifyContent: 'center', boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)', border: '1px solid #e2e8f0', '& .MuiButton-root': { borderRadius: '10px', textTransform: 'none', fontWeight: '600', px: 3, }, '& .MuiButton-contained': { background: '#3b82f6', '&:hover': {background: '#2563eb'}, }, }, }, }, }, blockOrder: defaultBlockOrder, })} </ViewProduct> ); }
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
organizationName | string | undefined | 商品を販売する組織の名前 |
imageUrl | string | 必須 | メイン商品画像のソースURL |
imageAlt | string | undefined | 商品画像のaltテキスト |
chips | Array<{label: string}> | 必須 | 表示するチップラベルの配列 |
headerTitle | string | 必須 | 商品のメインタイトルテキスト |
tags | Array<{label: string | string[]}> | 必須 | 単一または複数ラベルを持つタグの配列 |
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | 必須 | オプションのMUIアイコン付き情報セクションの配列 |
actions | Array<{label: ReactNode, onClick: () => void}> | undefined | アクションボタンの配列 |
className | string | undefined | コンテナスタイリング用の追加CSSクラス名 |
children | BlocksOverride | undefined | デフォルトレンダリングをオーバーライドするカスタムブロックコンポーネント |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
spacing | number | 2 | 子要素間のスペーシング |
注意: このコンポーネントはMUI StackProps を拡張し、すべてのStackコンポーネントプロパティを継承します。
サブコンポーネント
ViewProductコンポーネントは、異なるセクション用の複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
ViewProduct.CompanyName
組織名をヘッディングとして表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
organizationName | string | コンテキストから | 表示する組織名 |
children | ReactNode | コンテキストから | デフォルト会社名をオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは variant="h6" と component="h6" を持つMUI TypographyProps を拡張します。
ViewProduct.Image
メイン商品画像を表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
imageUrl | string | コンテキストから | 商品画像のソースURL |
imageAlt | string | コンテキストから | 商品画像のaltテキスト |
children | ReactNode | コンテキストから | デフォルト画像をオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI BoxProps を拡張します。
ViewProduct.Chips
商品チップを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
chips | Array<{label: string}> | コンテキストから | 表示するチップの配列 |
children | ReactNode | コンテキストから | デフォルトチップをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
注意: このコンポーネントは direction="row" と spacing={0.5} を持つMUI StackProps を拡張します。
ViewProduct.Title
商品タイトルをヘッディングとして表示します。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
headerTitle | string | コンテキストから | 表示するタイトルテキスト |
children | ReactNode | コンテキストから | デフォルトタイトルをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは variant="h6" と component="h6" を持つMUI TypographyProps を拡張します。
ViewProduct.Header
会社名、画像、チップ、タイトルを含む商品ヘッダーのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
organizationName | string | コンテキストから | ヘッダー用の組織名 |
imageUrl | string | コンテキストから | 商品画像URL |
imageAlt | string | コンテキストから | 商品画像altテキスト |
chips | Array<{label: string}> | コンテキストから | チップの配列 |
headerTitle | string | コンテキストから | 商品タイトル |
children | ReactNode | コンテキストから | デフォルトヘッダーコンテンツをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
注意: このコンポーネントは direction="column" と spacing={2} を持つMUI StackProps を拡張します。
ViewProduct.Sections
複数の情報セクションを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | コンテキストから | 表示するセクションの配列 |
children | ReactNode | コンテキストから | デフォルトセクションをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは direction="column" と spacing={0} を持つMUI StackProps を拡張します。
ViewProduct.Tags
商品タグを表示するコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tags | Array<{label: string | string[]}> | コンテキストから | 表示するタグの配列 |
children | ReactNode | コンテキストから | デフォルトタグをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
注意: このコンポーネントは direction="row" と spacing={0.5} を持つMUI StackProps を拡張します。
ViewProduct.Content
タグとセクションを含むメイン商品コンテンツのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tags | Array<{label: string | string[]}> | コンテキストから | タグの配列 |
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | コンテキストから | セクションの配列 |
organizationName | string | コンテキストから | 組織名 |
children | ReactNode | コンテキストから | デフォルトコンテンツをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントは direction="column" と spacing={2} を持つMUI StackProps を拡張します。
ViewProduct.Actions
アクションボタンのコンテナ。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
actions | Array<{label: ReactNode, onClick: () => void}> | コンテキストから | アクションボタンの配列 |
children | ReactNode | コンテキストから | デフォルトアクションをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
sx | SxProps | undefined | カスタムスタイリング用のMUI sxプロパティ |
注意: このコンポーネントは direction="row" と spacing={2} を持つMUI StackProps を拡張します。
🎨 設定例
Custom Styled Components
function StyledViewProductComponents() {
const chips: ProductChip[] = [{label: '新着'}];
const tags: ProductTag[] = [{label: 'プレミアム'}];
const sections: ProductSection[] = [{label: '価格', value: '¥19,900'}];
return (
<ViewProduct
organizationName="ストア"
imageUrl="/product.jpg"
headerTitle="商品タイトル"
chips={chips}
tags={tags}
sections={sections}
>
<ViewProduct.Header
sx={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '16px',
padding: '24px',
color: 'white',
}}
>
<ViewProduct.CompanyName />
<ViewProduct.Image />
<ViewProduct.Chips />
<ViewProduct.Title />
</ViewProduct.Header>
<ViewProduct.Content>
<ViewProduct.Tags />
<ViewProduct.Sections />
</ViewProduct.Content>
<ViewProduct.Actions />
</ViewProduct>
);
}
Block Override Pattern
function BlockOverrideViewProduct() {
const chips: ProductChip[] = [{label: 'セール'}];
const tags: ProductTag[] = [{label: '限定'}];
const sections: ProductSection[] = [{label: '在庫', value: '残り5個'}];
const actions: ProductAction[] = [{label: '今すぐ購入', onClick: () => {}}];
return (
<ViewProduct
organizationName="ショップ"
imageUrl="/product.jpg"
headerTitle="特別商品"
chips={chips}
tags={tags}
sections={sections}
actions={actions}
>
{({defaultBlocks}) => ({
blocks: {
...defaultBlocks,
header: {
...defaultBlocks.header,
props: {
...defaultBlocks.header.props,
sx: {backgroundColor: '#f8fafc', borderRadius: '12px'},
},
},
// Add custom banner block
customBanner: (
<div
style={{
padding: '12px 16px',
backgroundColor: '#fef3c7',
borderRadius: '8px',
textAlign: 'center',
color: '#92400e',
fontWeight: '600',
}}
>
🔥 特別オファー - 本日のみ20%オフ!
</div>
),
},
blockOrder: ['header', 'customBanner', 'content', 'actions'],
})}
</ViewProduct>
);
}
🔧 TypeScriptサポート
包括的な型定義による完全なTypeScriptサポート:
import {SvgIconComponent} from '@mui/icons-material';
import {ViewProduct} from '@nodeblocks/frontend-view-product-block';
import {ReactNode} from 'react';
// Chip type for product badges
interface ProductChip {
label: string;
}
// Tag type for product categories/features
interface ProductTag {
label: string | string[];
}
// Section type for product details
interface ProductSection {
icon?: SvgIconComponent;
label: string;
value: string;
}
// Action type for buttons
interface ProductAction {
label: ReactNode;
onClick: () => void;
}
function TypedViewProductExample() {
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 productData: CustomProductData = {
id: 'PROD-2024-001',
name: 'Premium Wireless Headphones',
price: 299.99,
category: 'Electronics',
brand: 'AudioTech',
availability: 'in-stock',
rating: 4.8,
features: ['Noise Cancellation', 'Bluetooth 5.0', 'Fast Charging'],
specifications: {
'Battery Life': '30 hours',
'Driver Size': '40mm',
Weight: '250g',
},
};
const chips: ProductChip[] = [{label: 'Best Seller'}, {label: 'Free Shipping'}];
const tags: ProductTag[] = [{label: `${productData.rating} Rating`}, {label: productData.features}];
const sections: ProductSection[] = [
{label: 'Brand', value: productData.brand},
{label: 'Category', value: productData.category},
{label: 'Price', value: `$${productData.price}`},
{label: 'Availability', value: productData.availability},
...Object.entries(productData.specifications).map(([key, value]) => ({
label: key,
value: value,
})),
];
const actions: ProductAction[] = [
{
label: 'Add to Cart',
onClick: () => console.log(`Added ${productData.name} to cart`),
},
{
label: 'Buy Now',
onClick: () => console.log(`Purchasing ${productData.name}`),
},
];
return (
<ViewProduct
organizationName="AudioTech Store"
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>
);
}
📝 注意事項
- コンポーネントはMUIの
Stackコンポーネントをベースとして使用し、柔軟なレイアウトオプションを提供します - すべてのサブコンポーネントはメインコンポーネントからコンテキスト値を自動的に受け取ります
tagsプロパティは単一の文字列と文字列の配列の両方をサポートします(" / "で結合して表示)sectionsプロパティはオプションのMUISvgIconComponentアイコンを受け入れます(提供されない場合はStickyNote2Outlinedがデフォルト)- アクションは
variant="contained"とsize="medium"を持つMUIButtonコンポーネントとしてレンダリングされます - チップは
variant="outlined"とcolor="primary"を持つMUIChipコンポーネントとしてレンダリングされます - コンポーネントは深いカスタマイズのためのブロックオーバーライドパターンを使用します
- デフォルトブロック:
header、content、actions - CSSクラスはBEMスタイルの命名に従います:
nbb-view-product、nbb-view-product-headerなど - 画像にはデフォルトスタイリングがあります:
maxHeight: '50vw'、aspectRatio: '1368/540'、objectFit: 'cover'
React、TypeScript、MUIを使用して❤️で構築されました。