Found while implementing #6004 (typing ObjectGrid.generateColumns() against the TableColumn[] slot it fills). Filed unassigned. Deliberately NOT folded into #6004, whose fence is what generateColumns() emits — this is a different seam (persistedColumns, downstream of it) and, unlike #6004's key census, this one has a user-visible symptom.
Measured (at 129c7a9e7)
packages/plugin-grid/src/ObjectGrid.tsx:2286 stamps the persisted width onto the column as size:
if(columnState.widths){persistedColumns=persistedColumns.map((col: any)=>{constsavedWidth=columnState.widths?.[col.accessorKey];if(savedWidth){return{ ...col,size: savedWidth};}returncol;});}packages/components/src/renderers/complex/data-table.tsxnever reads a column-level size. Its width resolution is, at all four sites (:1865, :1882, :2134, :2145):
columnWidths[col.accessorKey]||col.width||autoSizedWidths[col.accessorKey]
Three decisive checks, all on data-table.tsx:
| probe | result |
|---|
any col.size / column.size read | 0 |
setColumnWidths call sites | 1 — :1317, the resize handler only |
columnWidths seeded from the schema | never (useState<Record<string, number>>({}), :862) |
And ObjectGrid never passes a columnWidths prop down (0 occurrences in ObjectGrid.tsx).
So the round trip is broken at the last hop: resize → onColumnResize → localStorage → columnState.widths → size → dropped. TableColumn declares width, not size.
Symptom
Resize a grid column, reload the page: the width is not restored on the ungrouped path. It is written and read back correctly — only the key handed to the renderer is one nothing consumes.
Corroboration — grouped mode does it right
The grouped path builds its own map and stamps width (:3383-3387, via groupedColumnWidths), which data-table does read. Same component, same persisted source, two different keys, and only one of them works. That asymmetry is also what identifies the correct fix: width, not a new size read.
Why it stayed invisible
packages/plugin-grid/src/__tests__/columnStatePersistence.test.tsx pins only the outbound half (resize writes to localStorage and notifies the host). Its own docblock flags the shape of the gap:
seeds a width and re-reads it passes with the outbound half still dead
The inbound half — a seeded width actually reaching the rendered column — has no pin, so nothing failed.
Structurally it is #6004's family seen one seam later: an undeclared key written into a TableColumn[] slot that nothing reads. #6004 typed generateColumns()'s emit; this write happens after it, through a .map((col: any) => …) that #6004 deliberately left alone as out of fence.
Suggested direction (not a decision)
Write width instead of size, and pin the inbound half. Note the precedence in data-table — columnWidths[accessorKey] || col.width || autoSized — means a persisted width would lose to an in-session resize (correct) and beat auto-sizing (also correct), so no precedence change is needed. Sizing it properly should confirm nothing else consumes size and check the interaction with #6303 / #6259's width-default discussion.
Related
Generated by Claude Code
Generated by Claude Code
Found while implementing #6004 (typing
ObjectGrid.generateColumns()against theTableColumn[]slot it fills). Filed unassigned. Deliberately NOT folded into #6004, whose fence is whatgenerateColumns()emits — this is a different seam (persistedColumns, downstream of it) and, unlike #6004's key census, this one has a user-visible symptom.Measured (at
129c7a9e7)packages/plugin-grid/src/ObjectGrid.tsx:2286stamps the persisted width onto the column assize:packages/components/src/renderers/complex/data-table.tsxnever reads a column-levelsize. Its width resolution is, at all four sites (:1865,:1882,:2134,:2145):Three decisive checks, all on
data-table.tsx:col.size/column.sizereadsetColumnWidthscall sites:1317, the resize handler onlycolumnWidthsseeded from the schemauseState<Record<string, number>>({}),:862)And ObjectGrid never passes a
columnWidthsprop down (0 occurrences inObjectGrid.tsx).So the round trip is broken at the last hop: resize →
onColumnResize→ localStorage →columnState.widths→size→ dropped.TableColumndeclareswidth, notsize.Symptom
Resize a grid column, reload the page: the width is not restored on the ungrouped path. It is written and read back correctly — only the key handed to the renderer is one nothing consumes.
Corroboration — grouped mode does it right
The grouped path builds its own map and stamps
width(:3383-3387, viagroupedColumnWidths), whichdata-tabledoes read. Same component, same persisted source, two different keys, and only one of them works. That asymmetry is also what identifies the correct fix:width, not a newsizeread.Why it stayed invisible
packages/plugin-grid/src/__tests__/columnStatePersistence.test.tsxpins only the outbound half (resize writes to localStorage and notifies the host). Its own docblock flags the shape of the gap:The inbound half — a seeded width actually reaching the rendered column — has no pin, so nothing failed.
Structurally it is #6004's family seen one seam later: an undeclared key written into a
TableColumn[]slot that nothing reads. #6004 typedgenerateColumns()'s emit; this write happens after it, through a.map((col: any) => …)that #6004 deliberately left alone as out of fence.Suggested direction (not a decision)
Write
widthinstead ofsize, and pin the inbound half. Note the precedence indata-table—columnWidths[accessorKey] || col.width || autoSized— means a persisted width would lose to an in-session resize (correct) and beat auto-sizing (also correct), so no precedence change is needed. Sizing it properly should confirm nothing else consumessizeand check the interaction with #6303 / #6259's width-default discussion.Related
generateColumns()is untyped (any[]), so nothing type-checks what it writes intoDataTableSchema.columns: TableColumn[]— the hole that hid #5853 and #5453 #6004 — the emit-boundary card this was found under (the same defect class, one seam earlier)wrapinto the DataTable column object, but nothing indata-table.tsxever reads it #5453 — an undeclaredwrapkey forwarded that nothing reads (same class, no user-visible symptom)data-tablereads two column keysTableColumndoes not declare —headerIconandfitContent#6424 —headerIcon/fitContent, keysdata-tablereads thatTableColumndoes not declareGenerated by Claude Code
Generated by Claude Code