Skip to content

ObjectGrid writes the persisted column width as size, a key data-table never reads — saved widths are dropped on the ungrouped path #6457

Description

@claude

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:

proberesult
any col.size / column.size read0
setColumnWidths call sites1:1317, the resize handler only
columnWidths seeded from the schemanever (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.widthssize → 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-tablecolumnWidths[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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:queue

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions