Skip to main content

Overlays

Overlays cover the grid body for the two states where there are no rows to show: loading and empty. Both have sensible defaults and are fully replaceable.

Loading

Set loading and the body shows shimmering skeleton rows (the header, toolbar, and footer stay put so the layout doesn't jump):

<DataTable columns={columns} data={rows} loading={isFetching} enablePagination />
PropTypeDefaultUse case
loadingbooleanfalseToggle the loading overlay (e.g. from a query's isLoading).
skeletonRowsnumber5How many skeleton rows to draw — match your typical page size to avoid a jump.

In server mode the grid manages loading itself around onFetchData; wire the prop yourself only for client-side async.

Empty (no rows)

When there are zero rows (no data, or a filter matched nothing), the body shows an empty-state message:

<DataTable columns={columns} data={[]} noRowsMessage="No expenses match your filters" />

noRowsMessage takes a string or any React node, so you can render an illustration, a "Clear filters" button, or a call to action:

<DataTable
columns={columns}
data={rows}
noRowsMessage={
<Stack alignItems="center" spacing={1} sx={{ py: 4 }}>
<InboxOutlined color="disabled" />
<Typography color="text.secondary">Nothing here yet</Typography>
<Button size="small" onClick={addFirst}>Add the first row</Button>
</Stack>
}
/>

Replace the overlay component

For full control over markup and animation, swap the overlay slot entirely:

<DataTable
columns={columns}
data={rows}
slots={{
loadingOverlay: MyLinearProgressOverlay,
noRowsOverlay: MyEmptyState,
}}
/>
SlotReplaces
loadingOverlaythe skeleton/loading overlay
noRowsOverlaythe empty-state overlay (noRowsMessage is the default's content)
Keep the height stable

Give your custom overlay a min-height (or render inside a fixed height grid) so the card doesn't collapse when it has no rows.