View Product Block
The ViewProduct Component is a fully customizable product display component built with TypeScript and MUI. It provides a complete interface for viewing product details including organization information, product images, chips, tags, sections, and customizable actions with modern design patterns.
π Installationβ
npm install @nodeblocks/frontend-view-product-block@0.2.0
π Usageβ
import {ViewProduct} from '@nodeblocks/frontend-view-product-block';
- Basic Usage
- Advanced Usage
function BasicViewProduct() { const chips: ProductChip[] = [{label: 'New'}, {label: 'Featured'}]; const tags: ProductTag[] = [{label: 'Premium'}, {label: ['Electronics', 'Mobile']}]; const sections: ProductSection[] = [ {label: 'Model', value: 'iPhone 15 Pro'}, {label: 'Price', value: '$999'}, {label: 'Availability', value: 'In Stock'}, ]; const actions: ProductAction[] = [ {label: 'Add to Cart', onClick: () => console.log('Added to cart')}, {label: 'Buy Now', onClick: () => console.log('Buy now clicked')}, ]; return ( <ViewProduct organizationName="TechStore" imageUrl="/img/undraw_docusaurus_react.svg" imageAlt="iPhone 15 Pro" chips={chips} headerTitle="iPhone 15 Pro - Latest Model" 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: 'Bestseller'}, {label: 'Fast Shipping'}, {label: 'Limited Edition'}]; const tags: ProductTag[] = [{label: '4.9 Premium Rating'}, {label: ['Certified', 'Secure', 'Premium']}]; const sections: ProductSection[] = [ {label: 'Model', value: 'MacBook Pro 16" M3 Max'}, {label: 'Price', value: '$3,499'}, {label: 'Stock', value: 'In Stock - 12 left'}, {label: 'Delivery', value: 'Free Next-Day'}, {label: 'Warranty', value: '3 Years AppleCare+'}, ]; const actions: ProductAction[] = [ {label: 'Add to Cart', onClick: () => console.log('Added to cart')}, {label: 'Buy Now', onClick: () => console.log('Buy now clicked')}, {label: 'Add to Wishlist', onClick: () => console.log('Added to wishlist')}, ]; return ( <ViewProduct organizationName="Apple Store Premium" imageUrl="/img/undraw_docusaurus_react.svg" imageAlt="MacBook Pro 16 M3 Max" chips={chips} headerTitle="MacBook Pro 16 Ultimate Performance" 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', }} > Product Details </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> ); }
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
organizationName | string | undefined | Name of the organization selling the product |
imageUrl | string | Required | Source URL for the main product image |
imageAlt | string | undefined | Alt text for the product image |
chips | Array<{label: string}> | Required | Array of chip labels to display |
headerTitle | string | Required | Main title text for the product |
tags | Array<{label: string | string[]}> | Required | Array of tags with single or multiple labels |
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | Required | Array of information sections with optional MUI icons |
actions | Array<{label: ReactNode, onClick: () => void}> | undefined | Array of action buttons |
className | string | undefined | Additional CSS class name for styling the container |
children | BlocksOverride | undefined | Custom block components to override default rendering |
sx | SxProps | undefined | MUI sx prop for custom styling |
spacing | number | 2 | Spacing between child elements |
Note: This component extends MUI StackProps, inheriting all Stack component props.
Sub-Componentsβ
The ViewProduct component provides several sub-components for different sections. All sub-components receive their default values from the main component's context and can override these values through props.
ViewProduct.CompanyNameβ
Displays the organization name as a heading.
| Prop | Type | Default | Description |
|---|---|---|---|
organizationName | string | From context | Organization name to display |
children | ReactNode | From context | Custom content to override default company name |
className | string | undefined | Additional CSS class name for styling |
Note: This component extends MUI TypographyProps with variant="h6" and component="h6".
ViewProduct.Imageβ
Displays the main product image.
| Prop | Type | Default | Description |
|---|---|---|---|
imageUrl | string | From context | Source URL for the product image |
imageAlt | string | From context | Alt text for the product image |
children | ReactNode | From context | Custom content to override default image |
className | string | undefined | Additional CSS class name for styling |
Note: This component extends MUI BoxProps.
ViewProduct.Chipsβ
Container for displaying product chips.
| Prop | Type | Default | Description |
|---|---|---|---|
chips | Array<{label: string}> | From context | Array of chips to display |
children | ReactNode | From context | Custom content to override default chips |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps | undefined | MUI sx prop for custom styling |
Note: This component extends MUI StackProps with direction="row" and spacing={0.5}.
ViewProduct.Titleβ
Displays the product title as a heading.
| Prop | Type | Default | Description |
|---|---|---|---|
headerTitle | string | From context | Title text to display |
children | ReactNode | From context | Custom content to override default title |
className | string | undefined | Additional CSS class name for styling |
Note: This component extends MUI TypographyProps with variant="h6" and component="h6".
ViewProduct.Headerβ
Container for the product header including company name, image, chips, and title.
| Prop | Type | Default | Description |
|---|---|---|---|
organizationName | string | From context | Organization name for the header |
imageUrl | string | From context | Product image URL |
imageAlt | string | From context | Product image alt text |
chips | Array<{label: string}> | From context | Array of chips |
headerTitle | string | From context | Product title |
children | ReactNode | From context | Custom content to override default header content |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps | undefined | MUI sx prop for custom styling |
Note: This component extends MUI StackProps with direction="column" and spacing={2}.
ViewProduct.Sectionsβ
Container that displays multiple information sections.
| Prop | Type | Default | Description |
|---|---|---|---|
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | From context | Array of sections to display |
children | ReactNode | From context | Custom content to override default sections |
className | string | undefined | Additional CSS class name for styling |
Note: This component extends MUI StackProps with direction="column" and spacing={0}.
ViewProduct.Tagsβ
Container for displaying product tags.
| Prop | Type | Default | Description |
|---|---|---|---|
tags | Array<{label: string | string[]}> | From context | Array of tags to display |
children | ReactNode | From context | Custom content to override default tags |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps | undefined | MUI sx prop for custom styling |
Note: This component extends MUI StackProps with direction="row" and spacing={0.5}.
ViewProduct.Contentβ
Container for the main product content including tags and sections.
| Prop | Type | Default | Description |
|---|---|---|---|
tags | Array<{label: string | string[]}> | From context | Array of tags |
sections | Array<{icon?: SvgIconComponent, label: string, value: string}> | From context | Array of sections |
organizationName | string | From context | Organization name |
children | ReactNode | From context | Custom content to override default content |
className | string | undefined | Additional CSS class name for styling |
Note: This component extends MUI StackProps with direction="column" and spacing={2}.
ViewProduct.Actionsβ
Container for action buttons.
| Prop | Type | Default | Description |
|---|---|---|---|
actions | Array<{label: ReactNode, onClick: () => void}> | From context | Array of action buttons |
children | ReactNode | From context | Custom content to override default actions |
className | string | undefined | Additional CSS class name for styling |
sx | SxProps | undefined | MUI sx prop for custom styling |
Note: This component extends MUI StackProps with direction="row" and spacing={2}.
π¨ Configuration examplesβ
Custom Styled Componentsβ
function StyledViewProductComponents() {
const chips: ProductChip[] = [{label: 'New'}];
const tags: ProductTag[] = [{label: 'Premium'}];
const sections: ProductSection[] = [{label: 'Price', value: '$199'}];
return (
<ViewProduct
organizationName="Store"
imageUrl="/product.jpg"
headerTitle="Product Title"
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: 'Sale'}];
const tags: ProductTag[] = [{label: 'Limited'}];
const sections: ProductSection[] = [{label: 'Stock', value: '5 left'}];
const actions: ProductAction[] = [{label: 'Buy Now', onClick: () => {}}];
return (
<ViewProduct
organizationName="Shop"
imageUrl="/product.jpg"
headerTitle="Special Product"
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',
}}
>
π₯ Special Offer - 20% Off Today Only!
</div>
),
},
blockOrder: ['header', 'customBanner', 'content', 'actions'],
})}
</ViewProduct>
);
}
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
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>
);
}
π Notesβ
- The component uses MUI's
Stackcomponent as its base, providing flexible layout options - All sub-components automatically receive context values from the main component
- The
tagsprop supports both single strings and arrays of strings (displayed joined with " / ") - The
sectionsprop accepts optional MUISvgIconComponenticons (defaults toStickyNote2Outlinedif not provided) - Actions render as MUI
Buttoncomponents withvariant="contained"andsize="medium" - Chips render as MUI
Chipcomponents withvariant="outlined"andcolor="primary" - The component uses the Block Override Pattern for deep customization
- Default blocks are:
header,content,actions - CSS classes follow BEM-style naming:
nbb-view-product,nbb-view-product-header, etc. - Image has default styling:
maxHeight: '50vw',aspectRatio: '1368/540',objectFit: 'cover'
Built with β€οΈ using React, TypeScript, and MUI.