TableGrid
A bordered grid for rendering a headless table.
Every column is content-sized by default (ColumnWidth.Auto, equivalent to table-layout: auto); pin a column to a width by returning ColumnWidth.Fixed from columnWidth. Rows and cells are declared through content; a cell may span columns for grouped headers. The column count is derived from the widest row.
Implementation note (intrinsics). TableGrid measures cells through a SubcomposeLayout and deliberately does not query intrinsic widths or heights. Querying an intrinsic recursively re-composes any nested SubcomposeLayout — every Material OutlinedTextField contains one — and that recursive re-composition can jam the main thread long enough to time out the IME's InputConnection, causing a filter text field inside the grid to silently reject input. The per-cell border is drawn by a separate empty bordered Box sized to the grid slot, so a column-spanning grouped header still gets one full border.
Implementation note (recomposition). Marked NonRestartableComposable so TableGrid always re-runs when its caller recomposes (and the builder rebuilds cells from current engine state). Without this, Compose's parameter-equality skip can drop the recomposition when the content lambda's captures look stable (for example, if it only captures the long-lived Table reference), leaving the grid showing stale header / cell order after setColumnOrder and similar state changes. Anything composed inside content inherits the same re-run cadence; you do not need to annotate your own cell composables.
Parameters
applied to the outer SubcomposeLayout.
per-column width policy, indexed from 0.
color of the per-cell border. Defaults to a neutral grey.
inner padding between the border and cell content.
row/cell builder.