Skip to content

Table

A grid of cells with columns aligned across every row — the one thing Row/Column can’t do, since they size each row independently.

See also: DataTable for large or virtualized data sets · TreeTable for hierarchies.

Import: package:fleury/fleury.dart, or package:fleury/fleury_core.dart in browser code.

Table(
selectable: true,
header: const <Widget>[Text('Name'), Text('Role'), Text('Commits')],
rows: const <List<Widget>>[
<Widget>[Text('dan'), Text('author'), Text('1284')],
<Widget>[Text('ada'), Text('reviewer'), Text('642')],
<Widget>[Text('lin'), Text('docs'), Text('219')],
],
)

Each column’s width is negotiated once over all rows (and the header), per columnWidths; cells then lay out into those shared widths so columns line up. Supply header for a top row with a rule beneath it (style its cells yourself).

Cells should be content-sized (e.g. Text). Intrinsic columns measure cells with unbounded width, so a greedy cell that fills its main axis (a Column/Row with MainAxisSize.max) isn’t a valid cell — wrap it in a SizedBox if you need fixed dimensions.

Set selectable (or pass a controller / onSelect) to make the table keyboard-navigable: Up/Down move a highlighted row, Home/End jump, PageUp/PageDown page, and Enter fires onSelect. Arrow and pointer selection report onFocusedItemChanged. When interactive, Ctrl+C and semantic copy export the highlighted row as TSV or CSV through the framework clipboard service and report a TableCopyResult to onCopy. When an interactive table with a highlighted row is given a bounded height (e.g. inside an Expanded or SizedBox) and the body is taller than the viewport, it scrolls — the header stays pinned; a non-interactive table is clipped instead. Keyboard navigation reveals the current row; the wheel moves only the viewport and leaves the cursor alone (ListView / DataTable parity). Column widths are still negotiated over all rows, so columns never jitter as you scroll.

ParameterTypeDefaultDescription
rows:List<List<Widget>>requiredBody rows; each is a list of cell widgets. Short rows are padded and long rows trimmed to the column count.
header:List<Widget>?—Optional header cells (style them yourself). Drawn as the top row and included in column-width negotiation.
columnWidths:List<TableColumnWidth>?—Per-column sizing. Defaults to all-intrinsic.
columnSpacing:int1Blank cells between columns.
headerSeparator:booltrueDraw a horizontal rule under the header (when a header is present).
separatorStyle:CellStyleCellStyle.noneStyle for the header rule.
selectable:boolfalseWhether the table is keyboard-navigable with a highlighted row. Implied when a controller or onSelect is supplied.
controller:TableController?—External selection state. If null and the table is interactive, one is created and disposed internally.
focusNode:FocusNode?—External focus node for the interactive table.
autofocus:boolfalseRequest focus on first mount (interactive tables only).
onSelect:void Function(int index)?—Called with the body-row index when Enter activates a row.
onFocusedItemChanged:void Function(int index)?—Reports user navigation to a different row (keyboard, click, or semantic focus/select). Scrolling and programmatic controller writes do not fire it — ListView / DataTable parity.
copySelectedRow:booltrueWhether Ctrl+C and semantic copy export the highlighted row. Only applies while the table is interactive.
copyOptions:TableCopyOptionsconst TableCopyOptions()Export and clipboard options used when copying table data.
onCopy:void Function(TableCopyResult result)?—Called after a copy attempt completes.
selectedStyle:CellStyle?—Style merged into the highlighted row while the table has focus. Defaults to the theme’s selection style. Without focus, the row uses the theme’s muted style instead.
sortColumnIndex:int?—The header column the data is sorted by (renders nothing on its own — supply a ▲/▼ in your header cell — but exposes the sort state in the header cell’s semantics so assistive tech / the serve bridge can announce it, the WAI-ARIA aria-sort analog).
sortAscending:booltrueDirection of sortColumnIndex: ascending when true, descending otherwise.
semanticLabel:String?'Table'Label exposed through the semantic app graph.

Table is defined in packages/fleury/lib/src/catalog/table.dart.

Category: Lists & data · All widgets