Skip to main content
Accepted 2026-10-31 by the owner: on consolidating the data components ”=> yes”, and the same day “all accepted merege and proceed”, and the ADR itself “all confirmed” (design-system session c6, STA-1371). It supersedes the resource-query part of 0318 (ResourceQuery, ResourceQueryContractProps, FilterState and the query and onQueryChange props of DataTable and FilterBar), amends 0313 (Table’s sortDescriptor gives way to sort[]) and the 2026-10-28 DataGrid amendment of 0317 (DataGridColumn, rows, height, frozenColumns), and reverses the data-collection plan’s rule (owner, 2026-10-29) that DataTable and DataGrid “keep their APIs”.

Context

The owner asked why the data components seemed duplicated. A research audit (2026-10-31, stackra-notes/design-system-research-2026-10-31/data-family-audit.md) found that Table, DataTable, DataGrid and List were mostly proper layers, but the duplication sat around them: two engines (the app-held ResourceQuery of 0318 and the useCollection engine of the data-collection plan), three column types (TableColumn, CollectionColumn, DataGridColumn), two filter models with three filter UIs, three saved-view models with four UIs, two column visibility UIs and two pagers. It came from one day: the product-audit wave of 2026-10-28 built hidden columns, saved views, group-by and facets on ResourceQuery; seven hours later the data-collection plan built them again on the engine and, to keep the earlier work, said the old components “keep their APIs”. DataView had to hand DataTable a fake query, the same columns were declared up to three times, and the panel’s resource table kept a third copy of the state by hand.

Decision

1. Nine public components and one hook

2. One column type

CollectionColumn is the only column a data component takes. Its type is one enum, RuleFieldType: text, number, choice, date and boolean (it replaces DataGridCellType; select is now choice). It gains the editor’s fields: isEditable (DataTable edits it in place with onCellEdit), isReadOnly (DataGrid edits every column but these), isRequired, min, max and validate. TableColumn stays as the presentational subset Table reads; DataGridColumn, DataGridOption (now SelectItem), gridColumns and editableColumns are removed.

3. One filter model

CollectionFilter is the only filter. RuleOperator gains in, not_in, between, before, after, is_true and is_false; a condition’s value is a RuleValue, text or a list of text ([from, to] for between, an empty end open). A quick filter (a FilterBar chip, a FilterPanel facet) is one top-level condition with the id filter:<column> (quickFilterIdOf), so the bar, the panel and DataView on one engine show the same filter. The filter kind comes from the column: text contains, number and date between, choice in, boolean is_true or is_false. ruleMatches evaluates the new operators the same way on the client and the server.

4. One saved-views model

A saved view is a CollectionView of the engine. SavedViews draws it as a menu (apply, save, save as, rename, share, make default, delete), as tabs or as chips. A product’s database view store is a CollectionStore adapter.

5. One pager

The pager reads the engine’s paging (page, cursor with the cursors kept for Previous, or infinite). DataView owns it; DataTable and DataGrid draw it when they stand alone. Server mode without fetch takes the app’s nextCursor.

6. Old to new

These are no longer exported (internal parts): ColumnEditorPanel, ColumnMenu, CollectionFilterEditor, CollectionSortEditor, DataViewCards, DataViewBoard, CollectionRowPanel, DataTableCellEditor and DataGridEditor.

Consequences

  • One declaration of a dataset’s columns feeds the table, the grid, inline edit, the filters and the facets.
  • The breaking prop changes land at once, with every caller in the repository (playground, mobile, panel, docs, showcase registry) moved in the same change; there are no deprecated aliases.
  • A filter can no longer carry a menu icon, a disabled state, a placeholder, a number step or format, or custom yes and no words, because filters derive from columns; a column that should not be filtered sets isFilterable: false.
  • The panel’s resource table runs on useCollection in server mode and gains the board, cards, column editor and multi-sort it did not draw.

Enforcement

  • stackra gen --check and the showcase gen keep the generated API pages in step with the props.
  • The ui package’s tests cover the filter model (quick-filter.function.test.ts) and each component on the engine.