Table
Layout and sizing
Fit a small table, fill a page, or compose a custom layout.
On this page
Fit content or fill the page
layout="content" is the default. The table fits its rows, headers, and empty content and stops growing at 65dvh. Short tables have no vertical scrollbar unless their content exceeds that cap. An explicit height sets a fixed table viewport in this content layout.
Use layout="fill" for a table that should occupy the rest of the viewport:
<DataTable table={table} filters={filters} layout="fill" toolbar={<ProjectActions />} />Fill layout measures from the component's unscrolled page position to the bottom of the viewport. It accounts for ancestor bottom padding and borders, and remeasures when the viewport resizes or content above the table changes size. DataTable reserves space for its filter toolbar, column settings, pagination, and footer. In fill layout, layout controls the height and takes precedence over height.
The frame has a default minimum height of 240px. A table below a dashboard or other content therefore stays usable even when it starts below the fold. The page can scroll when that minimum cannot fit in the remaining viewport. Set minHeight to reserve more space; it includes the toolbar and footer, and only applies to fill layout:
<DataTable table={table} layout="fill" minHeight={400} />Scrolling the page does not change the measured height. This also keeps a resize after scrolling from making the table progressively taller.
Keep custom controls in the toolbar
filters provides the standard filter bar. Use toolbarStart for custom search, tabs, or other controls, and toolbar for actions. Column settings remain built in; controls wrap on small screens.
<DataTable
table={table}
filters={filters}
filterBar={false}
toolbarStart={<TableFilters filters={filters} searchPlaceholder="Find projects" />}
toolbar={<ProjectActions />}
layout="fill"
/>Keep filters attached when replacing its presentation so query resets and empty-result recovery still work. toolbarStart can also be used without a filter controller. When the built-in filter bar is visible, custom start controls appear beside it.
Column widths
Data columns share spare width, so the last header does not stretch independently of its cells. Configure each column through defineColumns:
| Option | Default | Purpose |
|---|---|---|
size | 180 | Starting width in pixels. |
minSize | 48 | Minimum width. |
maxSize | 1200 | Maximum width, including automatic growth. |
grow | 1 for data columns | Share of spare width. 2 gets twice the share; false keeps its size. |
pin | Unpinned | "start" or "end" for sticky columns. |
Display and selection columns do not grow unless configured. A manually resized column keeps its width; double-click its resize handle or reset column settings to restore automatic growth. These defaults can be changed through defaultColumn on the table controller.
On a narrow viewport, sticky positioning temporarily switches off if pinned columns would leave less than 120px for the center. The saved pinning preference remains intact.
Compose a full-page table
<div className="flex items-start justify-between gap-2">
<TableFilters filters={filters} />
<ProjectActions />
</div>
<TableView
table={table}
filters={filters}
layout="fill"
footer={<TablePagination table={table} />}
/>This composition assumes an existing table and filter controller, plus your action component. Import the table parts from @mendylanda/ui/table.
Content above TableView is reflected in its top position. Pass controls below the grid through footer so fill layout reserves their height. Keep the table in normal page flow; an ancestor with a fixed height or its own overflow still controls that container.
Expanded and wrapping rows
Use rowHeight="auto" when cells wrap. Return content from renderRowDetail(row) to expand a record, and null to collapse it. Details use the table viewport width so nested content can scroll independently.
Automatic row heights retain all columns for consistent measurement. See the performance guide before enabling them on very wide tables.
Empty and initial error content stays centered in the visible grid viewport, including in fill layout and when the columns overflow horizontally. Horizontal scrolling keeps this feedback in view.