Skip to content

List Engine

ListEngine is a generic, composable list-rendering primitive used for filterable, paginated list UIs where each item is custom-rendered.

It wraps useListEngineApi() and renders three sections:

  • header
  • list body
  • footer (pagination, when applicable)

From src/components/ListEngine/index.tsx:

  • ListEngine<T>()
  • useListEngineApi<T>()
  • ListEngineProps<T>
  • ListEngineRenderArgs<T>
  • ListEngineItemRenderArgs<T>
  • ListEngineFilterGroup
export type ListEngineFilterGroup = {
id: string;
label: string;
description?: string;
placement?: "header" | "panel";
order?: number;
};
export interface ListEngineItemRenderArgs<T> {
item: T;
index: number;
globalIndex: number;
page: number;
}
export interface ListEngineRenderArgs<T> {
items: readonly T[];
filteredItems: readonly T[];
allItems: readonly T[];
loading: boolean;
page: number;
totalPages: number;
pageSize: number;
filterState: FilterStateMap<T>;
rangeState: RangeStateMap<T>;
dateRangeState: DateRangeMap<T>;
setPage: Dispatch<SetStateAction<number>>;
setFilter: (key: keyof T, value: string) => void;
setRange: (key: keyof T, min: number | null, max: number | null) => void;
setDateRange: (key: keyof T, range: DateRange) => void;
clearFilters: () => void;
}
interface ListEngineProps<T extends Record<string, any>> {
title?: string;
label?: string;
data: readonly T[];
filters?: readonly Filter<T>[];
filterGroups?: readonly ListEngineFilterGroup[];
actions?: ReactNode;
loading?: boolean;
pageSize?: number;
initialFilters?: FilterStateMap<T>;
initialRangeState?: RangeStateMap<T>;
initialDateRanges?: DateRangeMap<T>;
listSize?: number | string;
itemKey?: (item: T, index: number) => string | number;
renderItem: (args: ListEngineItemRenderArgs<T>) => ReactNode;
emptyState?: ReactNode;
}

Supports filter types from BusinessTable/filters.tsx:

  • text
  • select
  • range
  • dateRange

placement controls where filters render:

  • "header" -> inline in header
  • "panel" -> inside SidePanel opened by Filters button

filterGroups allow grouped panel sections with label/description/order.

  • Pagination is enabled only when pageSize > 0.
  • Footer is rendered only when there is more than one page.
  • Page resets to 1 when data or any filter state changes.
  • loading=true shows a short loader bar in list area.
  • If not loading and no page items remain, emptyState is shown.
  • Default empty state text: No records found.

actions are rendered in a DropdownButton (kebab menu) in the header.

Header title resolves in this order:

  1. title
  2. label
  3. fallback: "List"
import ListEngine, { type ListEngineProps } from "@/components/ListEngine";
import type { Filter } from "@/components/BusinessTable/filters";
type UserRow = {
id: number;
name: string;
role: string;
createdAt: string;
};
const filters: Filter<UserRow>[] = [
{ type: "text", label: "Name", key: "name", placement: "header", placeholder: "Search users" },
{
type: "select",
label: "Role",
key: "role",
placement: "panel",
options: [
{ label: "Admin", value: "Admin" },
{ label: "User", value: "User" },
],
},
{ type: "dateRange", label: "Created", key: "createdAt", placement: "panel" },
];
<ListEngine<UserRow>
title="Users"
data={rows}
filters={filters}
pageSize={20}
itemKey={(row) => row.id}
renderItem={({ item }) => (
<div>
<strong>{item.name}</strong> - {item.role}
</div>
)}
/>;

Use this when you need custom layout around generated sections.

import { useListEngineApi } from "@/components/ListEngine";
const { header, list, footer, state } = useListEngineApi<UserRow>({
title: "Users",
data: rows,
filters,
pageSize: 20,
renderItem: ({ item }) => <UserCard user={item} />,
});
return (
<section>
{header}
<div style={{ marginTop: 12 }}>{list}</div>
{footer}
</section>
);

Use ListEngine when:

  • you need complex filter composition,
  • each row/item has custom markup,
  • you need pagination + filter state control.

Prefer DynamicTable for simpler table-like CRUD/read screens.

  • src/components/ListEngine/index.tsx
  • src/components/ListEngine/useListEngineApi.tsx
  • src/components/ListEngine/useListEngine.ts
  • src/components/ListEngine/useListFilterRendering.tsx
  • src/components/BusinessTable/filters.tsx