Skip to main content
DataTable wraps tanstack/react-table with a flat Python API. Hand it columns and rows, and it handles sorting, filtering, pagination, and formatting — no manual <TableRow> assembly required. For static display tables without interactivity, use Table instead.

Basic Usage

Pagination

For large datasets, paginated=True shows page controls and displays page_size rows at a time. Sorting and filtering still work across the full dataset — pagination just controls how many rows are visible. Set search=True to show a text input above the table that narrows visible rows across all columns. Search works alongside sorting and pagination — the search applies first, then sort order, then page boundaries.

Columns

DataTableColumn defines everything about a column: what data to show, how to size it, and how to style it.

Widths

Set width for fixed sizing, or min_width/max_width for flexible constraints. Without widths, columns auto-size to content.

Alignment

Right-align numbers so decimal points line up. Center short values like region codes. align applies to both the header and cells — it compiles to header_class and cell_class Python-side, so the protocol only sees CSS classes.

Styling

header_class and cell_class apply arbitrary Tailwind to individual columns — font weights, colors, monospace formatting, truncation. These are the escape hatches when align and width aren’t enough.

Rows

Click

Make rows clickable with on_row_click. The clicked row highlights and the action fires with the row’s data as $event. Use EVENT from prefab_ui.rx for a cleaner syntax than raw template strings.

Expandable

Wrap a row dict in ExpandableRow to make it expandable. Clicking the toggle reveals a full-width detail area below the row where you can put any component layout — text, badges, nested tables, charts, whatever fits. Rows without ExpandableRow render normally. Multiple rows can be expanded at the same time, and expanded state follows the row through sorting and pagination. Expandable rows work alongside all other DataTable features — sorting, search, pagination, row click, and component cells. The detail area is a single full-width canvas, not individual columns, so you have complete control over the layout.

Cells

Formatting

The format field applies an expression pipe to every value in a column. Any pipe that works in {{ value | pipe }} expressions works here — currency, percent:1, number:2, date:long, and any future pipes you add. See Pipes for the full list of available format pipes.

Components

Cell values can be full Prefab components — Badges, Sparklines, Progress bars, anything. Put a component instance directly in the row dict and it renders inline.

From DataFrame

Pass a pandas or polars DataFrame directly as rows. Columns auto-generate from the DataFrame’s column names — each column in the DataFrame becomes a DataTableColumn with key and header set to the column name. When you pass explicit columns, the key on each column must match a DataFrame column name — that’s how the table knows which data goes where. This lets you control headers, sorting, formatting, and alignment while the DataFrame provides the raw data.
import pandas as pd
from prefab_ui.components import DataTable, DataTableColumn

df = pd.DataFrame({
    "name": ["Arthur Dent", "Ford Prefect", "Trillian"],
    "score": [42, 87, 99],
    "region": ["Earth", "Betelgeuse", "Earth"],
})

# Auto-generate columns from df.columns
DataTable(rows=df)

# Custom columns — you control headers, sorting, formatting
DataTable(
    columns=[
        DataTableColumn(key="name", header="Hitchhiker", sortable=True),
        DataTableColumn(key="score", header="Score", align="right", format="number"),
    ],
    rows=df,
)
Works with any object that has .columns and .to_dict(orient="records") (pandas) or .to_dicts() (polars).

API Reference

DataTable Parameters

columns
list[DataTableColumn]
required
Column definitions. Auto-generated from DataFrame column names when rows is a DataFrame and columns is omitted.
rows
list[dict | ExpandableRow] | str | DataFrame
default:"[]"
Row data as a list of dicts or ExpandableRow wrappers, a {{ field }} interpolation reference, or a pandas/polars DataFrame.
Show a search input above the table for narrowing visible rows.
paginated
bool
default:"False"
Show pagination controls below the table.
page_size
int
default:"10"
Number of rows per page when paginated=True.
on_row_click
Action | list[Action] | None
default:"None"
Action(s) to fire when a row is clicked. $event is the row’s data dict. The clicked row highlights visually.
css_class
str | None
default:"None"
Additional Tailwind CSS classes for the table wrapper.

DataTableColumn Parameters

key
str
required
Data key — matches keys in the row dicts.
header
str
required
Column header display text.
sortable
bool
default:"False"
Enable click-to-sort on this column.
format
str | None
default:"None"
Expression pipe to apply to every cell value (e.g. "currency", "percent:1", "date:long"). Uses the same pipe system as {{ value | pipe }} expressions. Ignored when the cell value is a component.
width
str | None
default:"None"
Column width as a CSS value (e.g. "200px", "30%").
min_width
str | None
default:"None"
Minimum column width as a CSS value.
max_width
str | None
default:"None"
Maximum column width as a CSS value.
align
str | None
default:"None"
Text alignment for both header and cells: "left", "center", or "right". Resolves to header_class and cell_class Python-side.
header_class
str | None
default:"None"
Tailwind classes applied to the header cell for this column.
cell_class
str | None
default:"None"
Tailwind classes applied to every data cell in this column.

ExpandableRow Parameters

data
dict[str, Any]
required
Column values for the row — same format as a plain row dict.
detail
Component
required
Component tree rendered in a full-width area when the row is expanded.

Protocol Reference

DataTable
{
  "type": "DataTable",
  "columns": "[DataTableColumn] (required)",
  "rows?": "dict[] | string",
  "search?": false,
  "paginated?": false,
  "pageSize?": 10,
  "onRowClick?": "Action | Action[]",
  "cssClass?": "string"
}
DataTableColumn
{
  "key": "string (required)",
  "header": "string (required)",
  "sortable?": false,
  "format?": "string",
  "width?": "string",
  "minWidth?": "string",
  "maxWidth?": "string",
  "headerClass?": "string",
  "cellClass?": "string"
}
For the complete protocol schema, see DataTable, DataTableColumn.