Skip to main content

List Products Table Block

The ListProductsTable Component is a fully customizable and accessible products table interface built with React and TypeScript. It provides a complete tabular product listing experience with modern design patterns, sortable columns, action dropdowns, tabs, publication status management, pagination support, loading states, and flexible customization options for advanced product management applications.


🚀 Installation

npm install @nodeblocks/frontend-list-products-table-block

📖 Usage

import {ListProductsTable} from '@nodeblocks/frontend-list-products-table-block';
Live Editor
function BasicListProductsTable() {
  const [currentTab, setCurrentTab] = useState('published');
  const [isLoading, setIsLoading] = useState(false);

  const productData = [
    {
      id: '1',
      title: 'Premium Office Chair',
      category: 'Furniture',
      createdAt: '2024-01-15T10:30:00Z',
      updatedAt: '2024-01-16T14:20:00Z',
      numberOfApplicants: '5',
      publication: {
        since: '2024-01-15T00:00:00Z',
        until: '2024-03-15T23:59:59Z',
        status: 'ACTIVE'
      }
    },
    {
      id: '2',
      title: 'Wireless Headphones',
      category: 'Electronics',
      createdAt: '2024-01-14T09:15:00Z',
      updatedAt: '2024-01-14T09:15:00Z',
      numberOfApplicants: '12',
      publication: {
        since: '2024-01-20T00:00:00Z',
        until: '2024-04-20T23:59:59Z',
        status: 'INACTIVE'
      }
    }
  ];

  const tabs = [
    { label: 'Published Products' },
    { label: 'Draft Products' },
    { label: 'Archived Products' }
  ];

  const labels = {
    emptyStateMessage: 'No products found',
    actions: {
      createProduct: 'Create Product'
    },
    headerRow: {
      title: 'Product Title',
      publicationPeriod: 'Publication Period',
      createdAt: 'Created At',
      updatedAt: 'Updated At',
      numberOfApplicants: 'Applicants'
    },
    rowActions: {
      public: 'Make Public',
      private: 'Make Private',
      edit: 'Edit Product',
      archive: 'Archive Product',
      unarchive: 'Unarchive Product'
    },
    unsetData: {
      since: 'Not set',
      until: 'Not set',
      date: 'No publication period'
    }
  };

  const handleProductPublic = (productId, title) => {
    console.log('Product made public:', productId, title);
  };

  const handleProductPrivate = (productId, title) => {
    console.log('Product made private:', productId, title);
  };

  const handleProductArchive = (productId, title) => {
    console.log('Product archived:', productId, title);
  };

  const handleProductUnarchive = (productId) => {
    console.log('Product unarchived:', productId);
  };

  const handleNavigate = (path) => {
    console.log('Navigate to:', path);
  };

  const getRowHref = (row) => `/products/${row.id}`;
  const getUpdateRowHref = (row) => `/products/${row.id}/edit`;

  return (
    <ListProductsTable
      listProductsTableTitle="Product Management"
      labels={labels}
      isLoading={isLoading}
      onNavigate={handleNavigate}
      onProductPublic={handleProductPublic}
      onProductPrivate={handleProductPrivate}
      onProductArchive={handleProductArchive}
      onProductUnarchive={handleProductUnarchive}
      data={productData}
      rowHref={getRowHref}
      updateRowHref={getUpdateRowHref}
      tabs={tabs}
      currentTab={currentTab}
      onTabChange={setCurrentTab}
      createHref="#products/new">
      <ListProductsTable.Header style={{display: 'flex', justifyContent: 'space-between'}}>
        <ListProductsTable.Title />
        <ListProductsTable.Action />
      </ListProductsTable.Header>
      <ListProductsTable.Content>
        {isLoading ? (
          <ListProductsTable.Loader />
        ) : (
          <>
            <ListProductsTable.Tabs />
            <ListProductsTable.Table />
          </>
        )}
      </ListProductsTable.Content>
    </ListProductsTable>
  );
}
Result
Loading...

🔧 Props Reference

Main Component Props

PropTypeDefaultDescription
listProductsTableTitleReactNodeRequiredTitle for the products table section
labelsTableLabelsRequiredLabels object for table headers, actions, and messages
isLoadingbooleanundefinedWhether the table is currently loading
onNavigate(to: string) => voidRequiredCallback function for navigation
onProductPublicProductActionRequiredCallback function when product is made public
onProductPrivateProductActionRequiredCallback function when product is made private
onProductArchiveProductActionRequiredCallback function when product is archived
onProductUnarchive(productId: string) => voidRequiredCallback function when product is unarchived
dataListProductsTableRowData[]RequiredArray of product data objects
rowHref(row: ListProductsTableRowData) => stringRequiredFunction to generate row link URLs
updateRowHref(row: ListProductsTableRowData) => stringRequiredFunction to generate update row link URLs
tabsTab[]RequiredArray of tab configuration objects
currentTabstringundefinedCurrently active tab identifier
onTabChange(tab: string) => voidundefinedCallback function when tab is changed
createHrefstringRequiredURL for creating new products
pagination{currentPage: number; onPageChange: (page: number) => void; totalPages: number}From contextPagination configuration
classNamestringundefinedAdditional CSS class name for styling the container
childrenBlocksOverrideundefinedCustom block components to override default rendering

Sub-Components

The ListProductsTable component provides several sub-components that can be used independently:

ListProductsTable.Header

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default header rendering
classNamestringundefinedAdditional CSS class name for styling

ListProductsTable.Title

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default title rendering
classNamestringundefinedAdditional CSS class name for styling
sizeenum"3XL"Typography size for the title
colorenum"low-emphasis"Color theme for the title
weightenum"bold"Weight of the title

ListProductsTable.Action

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default action rendering
classNamestringundefinedAdditional CSS class name for styling
createHrefstringFrom contextURL for the create action button
labelsTableLabelsFrom contextLabels for action text
directionenum"row"Flex direction for action buttons
alignItemsenum"stretch"Alignment of items in the container
gapSizeenum"S"Gap between items in the container

ListProductsTable.Content

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default content rendering
classNamestringundefinedAdditional CSS class name for styling
isLoadingbooleanFrom contextLoading state from context

ListProductsTable.Loader

PropTypeDefaultDescription
childrenReactNodeCircular progress indicatorCustom loading indicator content
classNamestringundefinedAdditional CSS class name for styling
directionenum"row"Flex direction for action buttons
alignItemsenum"stretch"Alignment of items in the container
gapSizeenum"S"Gap between items in the container

ListProductsTable.Tabs

PropTypeDefaultDescription
tabsTab[]From contextArray of tab configuration objects
currentTabstringFrom contextCurrently active tab identifier
onTabChange(tab: string) => voidFrom contextTab change callback function
tabWidthstring"stretch"Width behavior for tabs
classNamestringundefinedAdditional CSS class name for styling

ListProductsTable.Table

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS class name for styling
onProductPublic(id: string, title: string) => voidFrom contextCallback function when product is made public
onProductPrivate(id: string, title: string) => voidFrom contextCallback function when product is made private
onProductArchive(id: string, title: string) => voidFrom contextCallback function when product is archived
onProductUnarchive(id: string) => voidFrom contextCallback function when product is unarchived
dataListProductsTableRowData[]From contextArray of table data
dropdownMenuItems(cell: ListProductsTableRowData) => Array<DropDownMenuItems>From contextFunction to generate dropdown menu items
dropdownMenuState{openedDropdownMenuId: string}From contextCurrently opened dropdown menu
setDropdownMenuState({openedDropdownMenuId: string}) => voidFrom contextCallback function when the opened dropdown menu changes
emptyState{icon?: IconType; message: string}From contextConfiguration for empty state
isLoadingbooleanFrom contextLoading state
onNavigate(to: string) => voidFrom contextNavigation callback function
pagination{currentPage: number; onPageChange: (page: number) => void; totalPages: number}From contextPagination configuration
rowHref`(cell: ListProductsTableRowData) => stringundefinednull`
updateRowHref`(cell: ListProductsTableRowData) => stringundefinednull`

🔧 TypeScript Support

Full TypeScript support with comprehensive type definitions:

import {ListProductsTable} from '@nodeblocks/frontend-list-products-table-block';

interface Tab {
isDisabled?: boolean;
key?: string;
label: string;
subtitle?: string;
}

interface ListProductsTableRowData {
category: string;
createdAt: string;
id: string;
numberOfApplicants: string;
publication?: {
since?: string;
status?: string;
until?: string;
};
title: string;
updatedAt: string;
}

interface CustomProductTableProps {
products: ListProductsTableRowData[];
onPublishProduct: (productId: string) => void;
onUnpublishProduct: (productId: string) => void;
onArchiveProduct: (productId: string) => void;
onRestoreProduct: (productId: string) => void;
tableTabs: Array<Tab>;
currentActiveTab: string;
onTabSwitch: (tab: string) => void;
isTableLoading: boolean;
}

const ProductTableComponent = ({
products,
onPublishProduct,
onUnpublishProduct,
onArchiveProduct,
onRestoreProduct,
tableTabs,
currentActiveTab,
onTabSwitch,
isTableLoading,
}: CustomProductTableProps) => {
const tableLabels = {
emptyStateMessage: 'No products available',
actions: {createProduct: 'New Product'},
headerRow: {
title: 'Product Name',
publicationPeriod: 'Publication Dates',
createdAt: 'Date Created',
updatedAt: 'Last Modified',
numberOfApplicants: 'Total Applicants',
},
rowActions: {
public: 'Publish',
private: 'Unpublish',
edit: 'Edit',
archive: 'Archive',
unarchive: 'Restore',
},
unsetData: {
since: 'Start date not set',
until: 'End date not set',
date: 'Publication period not configured',
},
};

return (
<ListProductsTable
listProductsTableTitle="Products Dashboard"
labels={tableLabels}
isLoading={isTableLoading}
onNavigate={path => console.log('Navigate:', path)}
onProductPublic={onPublishProduct}
onProductPrivate={onUnpublishProduct}
onProductArchive={onArchiveProduct}
onProductUnarchive={onRestoreProduct}
data={products}
rowHref={row => `/products/${row.id}`}
updateRowHref={row => `/products/${row.id}/edit`}
tabs={tableTabs}
currentTab={currentActiveTab}
onTabChange={onTabSwitch}
createHref="/products/create">
<ListProductsTable.Header />
<ListProductsTable.Content />
</ListProductsTable>
);
};

Built with ❤️ using React, TypeScript, and modern web standards.