List Order Block
The ListOrder Component is a fully customizable and accessible order list interface built with React and TypeScript. It provides a complete order listing experience with modern design patterns, clickable order cards, loading states, pagination support, and flexible customization options for order management applications.
π Installationβ
npm install @nodeblocks/frontend-list-order-block@0.1.1
π Usageβ
import {ListOrder} from '@nodeblocks/frontend-list-order-block';
- Basic Usage
- Advanced Usage
function SimpleListOrder() { const orders = [ { id: '1', logoUrl: 'https://placehold.co/600x400', title: 'Order #ORD-001', subtitle: '3 items - Electronics', date: '2024-01-15', status: 'delivered', statusLabel: 'Delivered', }, { id: '2', logoUrl: 'https://placehold.co/600x400', title: 'Order #ORD-002', subtitle: '1 item - Clothing', date: '2024-01-14', status: 'processing', statusLabel: 'Processing', }, { id: '3', logoUrl: 'https://placehold.co/600x400', title: 'Order #ORD-003', subtitle: '5 items - Home & Garden', date: '2024-01-13', status: 'shipped', statusLabel: 'Shipped', }, ]; return ( <ListOrder orders={orders} hasMore={false} onClickOrder={order => console.log('Order clicked:', order.id)}> <ListOrder.OrderListSection /> </ListOrder> ); }
function AdvancedListOrder() { const [hasMore, setHasMore] = useState(true); const [isLoading, setIsLoading] = useState(false); const orders = [ { id: '1', logoUrl: 'https://placehold.co/600x400', title: 'Premium Subscription', subtitle: 'Annual Plan - $249.99', date: '2024-01-20', status: 'delivered', statusLabel: 'Delivered', }, { id: '2', logoUrl: 'https://placehold.co/600x400', title: 'Software License', subtitle: 'Enterprise Edition - $149.50', date: '2024-01-19', status: 'processing', statusLabel: 'Processing', }, { id: '3', logoUrl: 'https://placehold.co/600x400', title: 'Hardware Kit', subtitle: 'Developer Pack - $89.00', date: '2024-01-18', status: 'shipped', statusLabel: 'Shipped', }, { id: '4', logoUrl: 'https://placehold.co/600x400', title: 'Consulting Session', subtitle: '2 Hours - $399.99', date: '2024-01-17', status: 'pending', statusLabel: 'Pending', }, { id: '5', logoUrl: 'https://placehold.co/600x400', title: 'Training Course', subtitle: 'Online Access - $75.00', date: '2024-01-16', status: 'cancelled', statusLabel: 'Cancelled', }, ]; const getStatusColor = (status) => { const colors = { delivered: {bg: '#dcfce7', text: '#166534'}, processing: {bg: '#dbeafe', text: '#1e40af'}, shipped: {bg: '#fef3c7', text: '#92400e'}, pending: {bg: '#f3f4f6', text: '#374151'}, cancelled: {bg: '#fee2e2', text: '#991b1b'}, }; return colors[status] || {bg: '#f3f4f6', text: '#374151'}; }; const handleLoadMore = () => { setIsLoading(true); setTimeout(() => { setIsLoading(false); setHasMore(false); }, 1500); }; const handleOrderClick = (order) => { console.log('View order:', order.id, order.title); }; return ( <ListOrder orders={orders} hasMore={hasMore} onClickOrder={handleOrderClick} onClickLoadMore={handleLoadMore} isLoadingList={isLoading} className="custom-list-order" > {({defaultBlocks, defaultBlockOrder}) => { const header = ( <div style={{ padding: '24px', borderBottom: '1px solid #e2e8f0', marginBottom: '16px', }} > <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', }} > <div> <div style={{ fontSize: '24px', fontWeight: '700', color: '#1e293b', marginBottom: '4px', }} > Order History </div> <p style={{fontSize: '14px', color: '#64748b', margin: 0}}>Manage and track your orders</p> </div> <div style={{ padding: '8px 16px', borderRadius: '8px', background: '#f1f5f9', fontSize: '14px', color: '#64748b', }} > {orders.length} orders </div> </div> </div> ); const customOrderList = ( <div style={{display: 'flex', flexDirection: 'column', gap: '12px', padding: '0 24px'}}> {orders.map(order => { const statusColors = getStatusColor(order.status); return ( <div key={order.id} onClick={() => handleOrderClick(order)} style={{ padding: '20px', borderRadius: '12px', border: '1px solid #e2e8f0', cursor: 'pointer', transition: 'all 0.2s ease', display: 'flex', alignItems: 'center', gap: '16px', }} > <img src={order.logoUrl} alt={order.title} style={{ width: '56px', height: '56px', borderRadius: '12px', objectFit: 'cover', }} /> <div style={{flex: 1}}> <div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '4px', }} > <span style={{ fontSize: '16px', fontWeight: '600', color: '#1e293b', }} > {order.title} </span> <span style={{ padding: '4px 12px', borderRadius: '20px', background: statusColors.bg, color: statusColors.text, fontSize: '12px', fontWeight: '600', }} > {order.statusLabel} </span> </div> <div style={{fontSize: '14px', color: '#64748b'}}>{order.subtitle}</div> </div> <div style={{textAlign: 'right'}}> <div style={{fontSize: '13px', color: '#94a3b8'}}>{order.date}</div> </div> </div> ); })} </div> ); const customLoadMore = hasMore ? ( <div style={{textAlign: 'center', padding: '24px'}}> <button onClick={handleLoadMore} disabled={isLoading} style={{ padding: '12px 32px', borderRadius: '10px', border: '1px solid #e2e8f0', background: '#ffffff', color: '#475569', fontSize: '14px', fontWeight: '500', cursor: isLoading ? 'not-allowed' : 'pointer', opacity: isLoading ? 0.6 : 1, }} > {isLoading ? 'Loading...' : 'Load More Orders'} </button> </div> ) : null; return { blocks: { ...defaultBlocks, header, orderListSection: customOrderList, loadMoreButton: customLoadMore, }, blockOrder: ['header', ...defaultBlockOrder], }; }} </ListOrder> ); }
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
orders | Order[] | Required | Array of order objects to display |
hasMore | boolean | Required | Whether there are more orders to load |
onClickOrder | (order: Order) => void | undefined | Callback function triggered when an order is clicked |
onClickLoadMore | () => void | undefined | Callback function triggered when load more button is clicked |
isLoadingList | boolean | undefined | Whether the list is currently loading |
className | string | undefined | Additional CSS class name for styling the container |
children | BlocksOverride | undefined | Function to override default blocks or custom component rendering |
Note: The main component inherits all HTML div element props.
Sub-Componentsβ
The ListOrder component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
ListOrder.OrderListSectionβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | undefined | Custom content to override default order list rendering |
className | string | undefined | Additional CSS class name for styling |
orders | Order[] | From context | Array of orders to display |
onClickOrder | (order: Order) => void | From context | Callback function for order click events |
Note: This component inherits all HTML div element props.
ListOrder.OrderCardβ
| Prop | Type | Default | Description |
|---|---|---|---|
order | Order | Required | Order object to display |
className | string | undefined | Additional CSS class name for styling |
onClick | () => void | undefined | Custom click handler for the order card |
children | ReactNode | undefined | Custom content to override default card rendering |
Note: This component inherits all HTML div element props.
ListOrder.OrderLogoβ
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | Required | URL of the organization logo |
alt | string | "Organization Logo" | Alternative text for the logo image |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML img element props.
ListOrder.OrderTitleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Title text for the order |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML h3 element props.
ListOrder.OrderSubtitleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Subtitle text for the order (typically organization name) |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML h4 element props.
ListOrder.OrderDateβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Date text for the order |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML div element props.
ListOrder.OrderLoadingCircleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default loading circle | Custom loading indicator content |
className | string | undefined | Additional CSS class name for styling |
width | string | "100" | Width of the loading circle |
height | string | "100" | Height of the loading circle |
Note: This component inherits all HTML svg element props.
ListOrder.LoadMoreButtonβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | "Read More" | Button text content |
className | string | undefined | Additional CSS class name for styling |
hasMore | boolean | From context | Whether more items are available to load |
onClickLoadMore | () => void | From context | Function to load more orders |
onClick | () => void | undefined | Custom click handler for the button |
disabled | boolean | Based on loading state | Whether the button is disabled |
Note: This component inherits all HTML button element props.
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {ListOrder} from '@nodeblocks/frontend-list-order-block';
import {ComponentProps} from 'react';
// Order data interface
export type Order = {
id: string;
logoUrl: string;
title: string;
subtitle: string;
date: string;
status: string;
statusLabel: string;
};
// Main component interface
interface ListOrderProps extends Omit<ComponentProps<'div'>, 'children'> {
orders: Order[];
hasMore: boolean;
onClickOrder?: (order: Order) => void;
onClickLoadMore?: () => void;
isLoadingList?: boolean;
className?: string;
}
// Usage example with full typing
function TypedListOrder() {
const orderData: Order[] = [
{
id: 'order-1',
logoUrl: 'https://placehold.co/600x400',
title: 'Premium Package',
subtitle: 'Annual subscription - 5 users',
date: '2024-01-20',
status: 'delivered',
statusLabel: 'Delivered',
},
{
id: 'order-2',
logoUrl: 'https://placehold.co/600x400',
title: 'Standard Package',
subtitle: 'Monthly subscription - 2 users',
date: '2024-01-19',
status: 'processing',
statusLabel: 'In Transit',
},
];
const handleOrderClick = (order: Order): void => {
console.log('Order selected:', order.id, order.title);
};
const handleLoadMore = (): void => {
console.log('Loading more orders...');
};
return (
<ListOrder
orders={orderData}
hasMore={true}
onClickOrder={handleOrderClick}
onClickLoadMore={handleLoadMore}
isLoadingList={false}
style={{
maxWidth: '800px',
margin: '0 auto',
padding: '24px',
border: '1px solid #e5e7eb',
borderRadius: '16px',
}}
>
<ListOrder.OrderListSection />
<ListOrder.LoadMoreButton />
</ListOrder>
);
}
Built with β€οΈ using React, TypeScript, and modern web standards.