Skip to main content

List Products Table Block

ListProductsTable is a controlled product-management table block built on MUI.

Installation

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

What You Need

ItemWhy it matters
listProductsTableTitleTitle or React Node for the table header
createHrefThe destination link/hash for the "Create Product" action button
dataArray of row data matching ListProductsTableRowData
labelsFull labels object mapping table headers, placeholders, action buttons, and empty/fallback states
Controlled state

ListProductsTable is presentational and does not manage internal state for filters, search keywords, tab selection, or pagination. Tab changes only update the active tab state; if you want the rows to change, filter the data you pass into the table yourself or by query new list and update that data in response to callbacks such as onTabChange and onPageChange.

Code Examples

Live Editor
function Example() {
  const [currentTab, setCurrentTab] = React.useState('published');
  const [page, setPage] = React.useState(1);
  const [lastAction, setLastAction] = React.useState('Navigation and row actions will appear here.');

  const products = [
    {
      id: '1',
      tab: 'draft',
      category: 'Furniture',
      title: 'Premium Office Chair',
      publication: { status: 'PUBLISHED', since: '2026-01-12', until: '2026-02-12' },
      createdBy: 'Marty',
      createdAt: '2026-01-10T09:21:00Z',
      updatedBy: 'Alice',
      updatedAt: '2026-01-11T10:30:00Z',
      favoritesCount: 14,
      ordersCount: 22,
    },
    {
      id: '2',
      tab: 'published',
      category: 'Electronics',
      title: 'Wireless Headphones',
      publication: { status: 'PUBLISHED', since: '2026-01-03', until: '2026-03-03' },
      createdBy: 'Ken',
      createdAt: '2026-01-02T09:21:00Z',
      updatedBy: 'Marty',
      updatedAt: '2026-01-05T10:30:00Z',
      favoritesCount: 34,
      ordersCount: 13,
    }
  ];

  const visibleProducts = products.filter((product) => product.tab === currentTab);

  const tabs = [
    { key: 'draft', label: 'Draft' },
    { key: 'published', label: 'Published' },
    { key: 'archived', label: 'Archived' },
  ];

  const labels = {
    emptyStateMessage: 'No products found',
    searchFieldPlaceholder: 'Search products',
    actions: {
      createProduct: 'Create Product',
      createProductShort: 'Create',
      filter: 'Filter',
    },
    headerRow: {
      productTitle: 'Product Title',
      publicationPeriod: 'Publication Period',
      created: 'Created',
      updated: 'Updated',
      favorites: 'Favorites',
      orders: 'Orders',
    },
    rowActions: {
      edit: 'Edit Product',
      archive: 'Archive Product',
      restore: 'Restore Product',
    },
    cellData: {
      sinceUnset: 'Not set',
      untilUnset: 'Not set',
      dateUnset: 'No publication period',
    },
  };

  return (
    <div style={{ minHeight: 450 }}>
      <ListProductsTable
        listProductsTableTitle="Product Management"
        createHref="#create"
        labels={labels}
        data={visibleProducts}
        tabs={tabs}
        currentTab={currentTab}
        onTabChange={setCurrentTab}
        onNavigate={(to) => setLastAction(`Navigating to: ${to}`)}
        pagination={{
          currentPage: page,
          totalPages: 1,
          onPageChange: setPage,
        }}
      />
      <div style={{marginTop: 12, color: '#475569', fontSize: 13}}>{lastAction}</div>
    </div>
  );
}
Result
Loading...

Important Props

Core Props

PropTypeRequiredDefaultDescription
dataListProductsTableRowData[]Yes-Array of product data objects to display
isLoadingbooleanNo-Switches table layout to loader mode when true
onNavigate(to: string) => voidNo-Navigation callback triggered on click actions (such as row clicks or create buttons)
onProductEdit(productId: string, title: string) => voidNo-Callback triggered when the "Edit" row menu action is clicked
onProductArchive(productId: string, title: string) => voidNo-Callback triggered when the "Archive" row menu action is clicked
onProductUnarchive(productId: string) => voidNo-Callback triggered when the "Restore" row menu action is clicked
resolveRowAction(row: ListProductsTableRowData) => ('edit' | 'archive' | 'restore')[] | undefinedNo-Evaluation callback mapping a row to active menu actions
shouldShowDropdownMenu(row: ListProductsTableRowData) => booleanNo-Conditional check to display or hide the dropdown row menu button entirely
paginationPaginationPropsNo-Stateful pagination controls: { currentPage, totalPages, onPageChange, className? }

Content Props

PropTypeRequiredDefaultDescription
listProductsTableTitleReactNodeYes-Title text or node rendered inside the Title sub-block
createHrefstringYes-Href passed to onNavigate callback on "Create Product" action click
labels{ emptyStateMessage: string; searchFieldPlaceholder: string; actions: { createProduct: string; createProductShort?: string; filter: string }; headerRow: { productTitle: string; publicationPeriod: string; created: string; updated: string; favorites: string; orders: string }; rowActions?: { edit: string; archive: string; restore: string }; cellData: { sinceUnset: string; untilUnset: string; dateUnset: string } }Yes-Direct map containing UI text configurations
rowHref(row: ListProductsTableRowData) => stringNo-Custom row link generator callback
ordersHref(row: ListProductsTableRowData) => stringNo-Direct link generator callback applied to the orders count
tabs{ key: string; label: string; isDisabled?: boolean; subtitle?: string }[]No-Product filtering tab definitions
currentTabstringNo-Key of the currently active/selected tab
onTabChange(tab: string) => voidNo-Switch callback triggered when another tab is clicked
searchValuestringNo-Active search input value
onSearchFieldChange(value: string) => voidNo-Callback triggered when typing inside the search input field
onSearchSubmit() => voidNo-Triggered when pressing Enter inside search input or clicking search button
onFilterButtonClick() => voidNo-Callback triggered when clicking the filter button next to search
searchChipsTitleReactNodeNo-Label displayed next to search chip container
searchChipsBaseTableSearchChip[]No-Active filters rendered as chips: { key, label }
onSearchChipDelete(chip: BaseTableSearchChip, index: number, event: SyntheticEvent) => voidNo-Callback triggered when dismissing an active filter chip

labels Structure

Provide exact translations and overrides inside the labels property matching this structure:

{
emptyStateMessage: string;
searchFieldPlaceholder: string;
actions: {
createProduct: string;
createProductShort?: string;
filter: string;
};
headerRow: {
productTitle: string;
publicationPeriod: string;
created: string;
updated: string;
favorites: string;
orders: string;
};
rowActions?: {
edit: string;
archive: string;
restore: string;
};
cellData: {
sinceUnset: string;
untilUnset: string;
dateUnset: string;
};
}

Layout and Composition Props

PropTypeRequiredDefaultDescription
childrenBlocksOverride | ReactNodeNo-Compound child elements or override function child
classNamestringNo-Custom styling class applied to the root element
sxSxPropsNo-MUI SX styling overrides passed to the outer Stack

ListProductsTable inherits all StackProps (except children). Default block order is ['header', 'searchChips', 'tabs', 'content', 'pagination'] (defaultBlockOrder).

Default UI Blocks

BlockBuilt onNotes
ListProductsTable (root)BaseTableMain tabular wrapper layout wrapping full table context
ListProductsTable.HeaderBaseTable.HeaderFlex container holding Title and Actions
ListProductsTable.TitleBaseTable.Header.TitleRenders the section header
ListProductsTable.ActionBaseTable.Header.ActionsFlex container holding search input, filters, and create actions
ListProductsTable.SearchChipsBaseTable.SearchChipsRenders active search filters as dismissible chips
ListProductsTable.TabsBaseTable.TabsResponsive tabs used for table filtering
ListProductsTable.ContentBaseTable.ContentOuter block wrapper for tables and loading spinners
ListProductsTable.LoaderBaseTable.Content.LoaderSpinner displayed during state transitions
ListProductsTable.TableBaseTable.Content.GridPrimary table grid presenting product metadata and row actions
ListProductsTable.PaginationBaseTable.PaginationControls footer pagination controls

TypeScript

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

const products: ListProductsTableRowData[] = [
{
id: 'prod-001',
category: 'Appliances',
title: 'Smart Smart Oven Pro',
publication: { status: 'PUBLISHED', since: '2026-05-15T00:00:00Z' },
createdBy: 'System admin',
createdAt: '2026-05-10T09:21:00Z',
updatedBy: 'System admin',
updatedAt: '2026-05-11T10:30:00Z',
favoritesCount: 15,
ordersCount: 3,
}
];

const tabs = [
{ key: 'published', label: 'Published Items' }
];

const labels = {
emptyStateMessage: 'No items',
searchFieldPlaceholder: 'Search catalog',
actions: { createProduct: 'New', filter: 'Filter' },
headerRow: {
productTitle: 'Product',
publicationPeriod: 'Period',
created: 'Created',
updated: 'Updated',
favorites: 'Favorites',
orders: 'Orders',
},
cellData: { sinceUnset: '-', untilUnset: '-', dateUnset: 'No schedule' },
};

<ListProductsTable
listProductsTableTitle="App Dashboard"
createHref="#new"
labels={labels}
data={products}
tabs={tabs}
currentTab="published"
/>;