Skip to main content

List Organizations Block

The ListOrganizations Component is a fully customizable and accessible organizations table interface built with React, TypeScript, and MUI. It provides a complete tabular organization listing experience with modern design patterns, audit status management, search functionality, tabs, row actions, pagination support, loading states, and flexible customization options for advanced organization management applications.


πŸš€ Installation​

npm install @nodeblocks/frontend-list-organization-block@0.2.1

πŸ“– Usage​

import {ListOrganizations} from '@nodeblocks/frontend-list-organization-block';
Live Editor
function SimpleListOrganizations() {
  const organizationData = [
    {
      id: '1',
      name: 'Acme Corporation',
      createdAt: '2021-03-15',
      joinDate: '2024-01-10',
      auditStatus: 'approved',
    },
    {
      id: '2',
      name: 'Tech Startup Inc',
      createdAt: '2022-06-20',
      joinDate: '2024-01-12',
      auditStatus: 'waiting_for_review',
    },
    {
      id: '3',
      name: 'Design Studio',
      createdAt: '2023-01-05',
      joinDate: '2024-01-14',
      auditStatus: 'rejected',
    },
  ];

  const tabs = [{label: 'All'}];

  const labels = {
    emptyStateMessage: 'No organizations found',
    searchFieldPlaceholder: 'Search organizations...',
    actions: {
      headerAction: 'Create Organization',
      rowAction: 'View Details',
    },
    headerRow: {
      createdAt: 'Created',
      name: 'Organization Name',
      joinDate: 'Join Date',
      auditStatus: 'Status',
    },
    cellData: {
      statusApproved: 'Approved',
      statusRejected: 'Rejected',
      statusWaitingForReview: 'Pending Review',
    },
  };

  return (
    <ListOrganizations
      data={organizationData}
      labels={labels}
      tabs={tabs}
      listOrganizationsTitle="My Organizations"
      onSearchFieldChange={value => console.log('Search:', value)}
      onActionClick={() => console.log('Create clicked')}
      onNavigate={to => console.log('Navigate to:', to)}
      onRowActionClick={row => console.log('Row action:', row.id)}
      rowHref={row => `/organizations/${row.id}`}
    >
      <ListOrganizations.Header />
      <ListOrganizations.Table />
    </ListOrganizations>
  );
}
Result
Loading...

πŸ”§ Props Reference​

Main Component Props​

PropTypeDefaultDescription
listOrganizationsTitleReactNodeRequiredTitle for the organizations table section
labelsOrganizationLabelsRequiredLabels object for table headers, actions, and messages
isLoadingbooleanundefinedWhether the table is currently loading
onSearchFieldChange(value: string) => voidRequiredCallback function when search field value changes
onActionClick() => voidRequiredCallback function for header action button
onNavigate(to: string) => voidRequiredCallback function for navigation
onRowActionClick(rowData: ListOrganizationsRowData) => voidRequiredCallback function when row action is clicked
dataListOrganizationsRowData[]RequiredArray of organization data objects
rowHref(row: ListOrganizationsRowData) => stringRequiredFunction to generate row link URLs
tabsTabData[]RequiredArray of tab configuration objects
currentTabstringundefinedCurrently active tab label
onTabChange(tab: string) => voidundefinedCallback function when tab is changed
paginationPaginationPropsundefinedPagination configuration object
classNamestringundefinedAdditional CSS class name for styling the container
childrenBlocksOverrideundefinedFunction to override default blocks

Note: The main component inherits MUI Stack props. Root container uses spacing={3} and sx={{ p: 3 }} by default.

Sub-Components​

The ListOrganizations 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.

ListOrganizations.Header​

Container for the header including title and action components.

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default header rendering
directionStackProps['direction']"row"Flex direction for layout
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Stack props. Default justifyContent: 'space-between'.

ListOrganizations.Title​

Displays the organizations section title.

PropTypeDefaultDescription
childrenReactNodeFrom contextCustom content to override title
listOrganizationsTitleReactNodeFrom contextTitle text when children not provided
variantTypographyProps['variant']"h4"MUI Typography variant
componentElementType"h1"HTML element to render
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Typography props.

ListOrganizations.Action​

Container for search field and action button.

PropTypeDefaultDescription
childrenReactNodeundefinedCustom content to override default action rendering
onActionClick() => voidFrom contextCallback for the action button
onSearchFieldChange(value: string) => voidFrom contextCallback for search input
labelsOrganizationLabelsFrom contextLabels for action text and placeholder
directionStackProps['direction']"row"Flex direction
spacingnumber2Stack spacing between elements
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Stack props.

ListOrganizations.Content​

Container for the main content area (loader, tabs, or table).

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

Note: This component inherits MUI Stack props with spacing={3}. Renders Loader when loading, Tabs + Table otherwise.

ListOrganizations.Loader​

Displays a loading indicator.

PropTypeDefaultDescription
childrenReactNodeCircularProgressCustom loading indicator content
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Stack props. Default alignment is alignItems: 'center', justifyContent: 'center'.

ListOrganizations.Tabs​

Displays tab navigation for filtering organizations.

PropTypeDefaultDescription
tabsTabData[]From contextArray of tab configuration objects
currentTabstringFrom contextCurrently active tab label
onTabChange(tab: string) => voidFrom contextTab change callback function
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Tabs props (except value, onChange, variant). Uses variant="fullWidth" by default.

ListOrganizations.Table​

Displays the organizations data in a table format.

PropTypeDefaultDescription
labelsOrganizationLabelsFrom contextLabels for table headers and actions
dataListOrganizationsRowData[]From contextArray of organization data
rowHref(row: ListOrganizationsRowData) => stringFrom contextFunction to generate row links
onNavigate(to: string) => voidFrom contextNavigation callback for row clicks
onRowActionClick(row: ListOrganizationsRowData) => voidFrom contextCallback when row action is clicked
paginationPaginationPropsFrom contextPagination configuration
spacingnumber3Stack spacing between elements
classNamestringundefinedAdditional CSS class name for styling

Note: This component inherits MUI Stack props.


🎨 Configuration examples​

Custom Header Styling​

<ListOrganizations.Header 
sx={{
bgcolor: 'primary.main',
color: 'white',
borderRadius: 2,
p: 3
}}
/>

Custom Title Styling​

<ListOrganizations.Title 
variant="h3"
sx={{
fontWeight: 700,
color: 'primary.main'
}}
/>

Custom Status Labels with JSX​

const labels = {
// ... other labels
cellData: {
statusApproved: <Chip label="Approved" color="success" size="small" />,
statusRejected: <Chip label="Rejected" color="error" size="small" />,
statusWaitingForReview: <Chip label="Pending" color="warning" size="small" />
}
};

Using Block Override Pattern​

<ListOrganizations {...props}>
{({defaultBlocks, defaultBlockOrder}) => ({
blocks: {
...defaultBlocks,
header: customHeader,
content: customContent,
},
blockOrder: defaultBlockOrder,
})}
</ListOrganizations>

πŸ”§ TypeScript Support​

Full TypeScript support with comprehensive type definitions:

import {ListOrganizations} from '@nodeblocks/frontend-list-organization-block';
import { StackProps } from '@mui/material';
import { ReactNode } from 'react';

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

// Row data interface
interface ListOrganizationsRowData {
id: string;
createdAt: string;
name: string;
joinDate: string;
auditStatus: string;
}

// Pagination props interface
interface PaginationProps {
className?: string;
currentPage: number;
onPageChange: (page: number) => void;
totalPages: number;
}

// Labels interface
interface OrganizationLabels {
emptyStateMessage: string;
searchFieldPlaceholder: string;
actions: {
headerAction: ReactNode;
rowAction: ReactNode;
};
headerRow: {
createdAt: string;
name: string;
joinDate: string;
auditStatus: string;
};
cellData: {
statusApproved: ReactNode;
statusRejected: ReactNode;
statusWaitingForReview: ReactNode;
};
}

// Main component props interface
interface ListOrganizationsProps<T extends TabData[]> extends Omit<StackProps, 'children'> {
listOrganizationsTitle: ReactNode;
labels: OrganizationLabels;
isLoading?: boolean;
onSearchFieldChange: (value: string) => void;
onActionClick: () => void;
onNavigate: (to: string) => void;
onRowActionClick: (rowData: ListOrganizationsRowData) => void;
data: ListOrganizationsRowData[];
rowHref: (row: ListOrganizationsRowData) => string;
tabs: T;
currentTab?: T[number]['label'];
onTabChange?: (tab: T[number]['label']) => void;
pagination?: PaginationProps;
children?: BlocksOverride;
}

// Usage example with full typing
function TypedListOrganizations() {
const [page, setPage] = useState(1);
const [currentTab, setCurrentTab] = useState('All');

const organizationData: ListOrganizationsRowData[] = [
{
id: 'org-1',
name: 'Tech Company',
createdAt: '2020-05-10',
joinDate: '2024-01-15',
auditStatus: 'approved',
},
{
id: 'org-2',
name: 'Startup Inc',
createdAt: '2022-08-20',
joinDate: '2024-01-18',
auditStatus: 'waiting_for_review',
},
];

const tabs: TabData[] = [
{key: 'all', label: 'All'},
{key: 'approved', label: 'Approved'},
{key: 'pending', label: 'Pending'},
];

const labels: OrganizationLabels = {
emptyStateMessage: 'No organizations found',
searchFieldPlaceholder: 'Search organizations...',
actions: {
headerAction: 'Create Organization',
rowAction: 'Manage',
},
headerRow: {
createdAt: 'Founded',
name: 'Organization Name',
joinDate: 'Member Since',
auditStatus: 'Audit Status',
},
cellData: {
statusApproved: 'Approved',
statusRejected: 'Rejected',
statusWaitingForReview: 'Under Review',
},
};

const handleSearchChange = (value: string): void => {
console.log('Search value:', value);
};

const handleNavigate = (to: string): void => {
console.log('Navigating to:', to);
};

const handleRowAction = (row: ListOrganizationsRowData): void => {
console.log('Managing organization:', row.id);
};

const pagination: PaginationProps = {
currentPage: page,
totalPages: 5,
onPageChange: newPage => setPage(newPage),
};

return (
<ListOrganizations
data={organizationData}
labels={labels}
tabs={tabs}
currentTab={currentTab}
onTabChange={tab => setCurrentTab(tab)}
listOrganizationsTitle="Organization List"
onSearchFieldChange={handleSearchChange}
onActionClick={() => console.log('Create clicked')}
onNavigate={handleNavigate}
onRowActionClick={handleRowAction}
rowHref={row => `/organizations/${row.id}`}
pagination={pagination}
isLoading={false}
sx={{
maxWidth: 800,
mx: 'auto',
p: 3,
border: '1px solid #e5e7eb',
borderRadius: 2,
}}
>
<ListOrganizations.Header />
<ListOrganizations.Tabs />
<ListOrganizations.Table />
</ListOrganizations>
);
}

πŸ“ Notes​

  • The root component uses MUI's Stack with default spacing={3} and sx={{ p: 3 }} padding
  • Uses MUI Table, TableContainer, TableHead, TableBody, and TableRow components
  • Date formatting uses luxon library with yyyy/M/d format for display
  • Row action button only appears for rows with auditStatus: 'waiting_for_review'
  • Empty state displays a person icon (SVG) with the emptyStateMessage from labels
  • Pagination uses MUI Pagination component with variant="outlined" and shape="rounded"
  • Table rows are clickable when rowHref returns a valid URL (cursor changes to pointer)
  • Tabs use MUI Tabs component with variant="fullWidth" by default
  • ListOrganizations.Title uses MUI Typography with default variant="h4" and component="h1"
  • Search field uses MUI TextField with a search icon in the end adornment
  • Action button uses MUI Button with variant="outlined" and size="medium"
  • All sub-components inherit their respective MUI component props and support the sx prop for styling
  • Block override pattern allows customizing, replacing, or reordering default blocks

Built with ❀️ using React, TypeScript, and MUI.