List View Component: Design Completeness Assessment
Date: 2026-03-17
Purpose
Section titled “Purpose”This document assesses whether the canary components defined in the Design (Waves 0-3b) are sufficient to migrate the canary-refactor stories from vendored components to canary equivalents, within the scope of grid data display and editing.
Context
Section titled “Context”The dev-witness stories render the full vendored ItemsPage production page. This page composes:
- Grid layer:
ItemTableAGGridwrappingArdaGridwith items-specific editing, draft management, and 30 column definitions - Page chrome:
AppSidebar,AppHeader, tabs, search bar, column visibility dropdown, action buttons - Panels:
ItemDetailsPanel(read-only detail view),ItemFormPanel(add/edit form) - Modals: Cards preview, import, delete confirmation
- Context providers: Auth, order queue, item cards, navigation blocking
The canary-refactor stories (per Workflow step 6) must swap vendored grid components for canary equivalents while retaining vendored imports for non-grid components. The result will be hybrid stories: canary grid infrastructure + vendored domain and page components.
Insufficiency Table
Section titled “Insufficiency Table”| # | Component / Feature | Classification | Used By | Recommendation | Decision |
|---|---|---|---|---|---|
| 1 | SortMenuHeader | Missing from Tier 2 scope | ArdaGrid (internal) | Add to Tier 2 scope. See detailed analysis. | Agreed |
| 2 | 9 Typeahead Cell Editors | Domain-specific (Tier 4) | ItemTableAGGrid | Retain vendored. See detailed analysis. | Add to new Section Follow Up Projects (Out of Scope) in the design.md document |
| 3 | SelectAllHeaderComponent | Domain-specific (Tier 4) | itemsColumnDefs | Retain vendored. See detailed analysis. | Replace with AG Grid native configuration in the canary |
| grid, validate shift-click behavior document | |||||
| 4 | QuickActionsCell | Domain-specific (Tier 4) | itemsColumnDefs | Retain vendored. See detailed analysis. | Add to new Section Follow Up Projects (Out of Scope) in the design.md document |
| 5 | CardCountCell | Domain-specific (Tier 4) | itemsColumnDefs | Retain vendored. See detailed analysis. | Agreed |
| 6 | NotesCell / CardNotesCell | Domain-specific (Tier 4) | itemsColumnDefs | Retain vendored. See detailed analysis. | In Scope, new type of cell (Memo) with its renderer and editor. The renderer should truncate the text to fit in the cell adding ellipsis. When hovered over, it should open an overlay to show the full text after a configurable delay of hover. |
| 7 | itemsColumnDefs / itemsDefaultColDef | Domain-specific (Tier 4) | ItemTableAGGrid | Fork into canary-refactor. See detailed analysis. | |
| 8 | Draft lifecycle management | Partially covered | ItemTableAGGrid | Hybrid approach. See detailed analysis. | Add to new Section Follow Up Projects (Out of Scope) in the design.md document |
| 9 | Page chrome components | Out of scope | ItemsPage | Retain vendored. See detailed analysis. | Add to new Section Follow Up Projects (Out of Scope) in the design.md document |
| 10 | ItemDetailsPanel / ItemFormPanel | Out of scope | ItemsPage | Retain vendored. See detailed analysis. | Agreed |
| 11 | Color cell editor with swatches | Domain-specific (Tier 4) | ItemTableAGGrid | Retain vendored. See detailed analysis. | Add to scope as a Color data type with its cell renderer and editor (Color Picker). |
Detailed Analysis
Section titled “Detailed Analysis”#1 — SortMenuHeader
Section titled “#1 — SortMenuHeader”What it is: A custom AG Grid header component (~100 lines) that replaces AG Grid’s default column header. It shows the column name, a sort-direction indicator (up/down arrow), and a ⋮ button that opens a portal dropdown menu with “Sort Ascending”, “Sort Descending”, and “Clear Sort” options.
Why it’s needed: The vendored ArdaGrid sets headerComponent: SortMenuHeader on defaultColDef, meaning every sortable column uses it. Without porting it, columns would fall back to AG Grid’s default header, producing a visually different grid. VRT tests would fail.
Implementation details:
- Uses
IHeaderParamsfromag-grid-community - Syncs sort state via
params.column.addEventListener('sortChanged', ...) - Dropdown rendered via
createPortal(...)todocument.bodyto escape AG Grid’s overflow clipping - Outside-click detection to close the dropdown
Recommendation: Port as an internal sub-component of the Tier 2 DataGrid<T> molecule. It is tightly coupled to DataGrid (set via defaultColDef.headerComponent) and not intended for standalone use. Add it to the Wave 2 scope:
- Source: Internal to
vendored/arda-frontend/components/table/ArdaGrid.tsx(lines 153-257) - Target:
canary/molecules/data-grid/sort-menu-header.tsx - Dependencies:
ag-grid-community(IHeaderParams),createPortalfrom React DOM - Tests: Port the existing behavior; add story demonstrating sort menu interaction
- CSS: Uses
.arda-sort-header,.arda-sort-header-text,.arda-sort-header-icon,.arda-sort-header-btn,.arda-sort-menu-dropdownclasses fromag-theme-arda.css(already in Wave 0 scope)
Action required: Update the Design Wave 2 table to include SortMenuHeader.
#2 — Typeahead Cell Editors
Section titled “#2 — Typeahead Cell Editors”What they are: 9 domain-specific AG Grid cell editors (SupplierCellEditor, UnitCellEditor, TypeCellEditor, SubTypeCellEditor, UseCaseCellEditor, FacilityCellEditor, DepartmentCellEditor, LocationCellEditor, SublocationCellEditor). Each wraps a domain-specific *Typeahead component that performs debounced API lookups (250ms) and renders a portal dropdown with search results.
Why they can’t be ported: Each editor is bound to a specific API endpoint (ardaClient.lookup* functions) and domain entity type. They require production API context that the Storybook stories mock via MSW handlers. They are Tier 4 (domain-specific) components.
Recommendation: Retain vendored. The canary-refactor ItemTableAGGrid fork will import these editors from vendored paths (@frontend/components/items/*CellEditor). The canary grid infrastructure (Tier 3a/3b) accepts arbitrary cellEditor components via AG Grid’s ColDef, so vendored editors plug into canary grids without modification.
#3 — SelectAllHeaderComponent
Section titled “#3 — SelectAllHeaderComponent”What it is: A custom AG Grid header component (~160 lines) for the selection checkbox column. Implements tri-state logic (all/some/none selected), shift-click range selection, and sync with AG Grid’s selection API.
Why it was originally classified as domain-specific: It is defined in columnPresets.tsx alongside the items-specific column definitions. It uses AG Grid’s GridApi methods (getDisplayedRowCount, getSelectedRows, selectAll, deselectAll, forEachNode) directly.
AG Grid native alternative: Since AG Grid v32+, the Community edition provides this functionality natively via the rowSelection configuration object:
rowSelection.headerCheckbox: true— renders a tri-state select-all checkbox in the header (all/some/none)rowSelection.selectAll: 'all' | 'filtered' | 'currentPage'— controls what “select all” meansselectionColumnDef— customizes the checkbox column (width, pinning, sortable, custom renderers, tooltips)- Shift-click range selection may be supported natively via
rowSelection.enableClickSelection
The vendored SelectAllHeaderComponent is a custom reimplementation of functionality that AG Grid already provides out of the box. The custom component adds shift-click range selection logic on top, but the tri-state header checkbox behavior is native.
Recommendation: Replace with AG Grid native rowSelection configuration in the canary DataGrid<T> (Tier 2). Configure headerCheckbox: true and selectionColumnDef to match the vendored visual appearance. Validate that shift-click range selection works natively; if not, document the gap for a follow-up. This eliminates a ~160-line custom component and a vendored dependency from the canary-refactor stories.
References:
#4 — QuickActionsCell
Section titled “#4 — QuickActionsCell”What it is: A cell renderer that displays action buttons per row: add to order queue, print labels, preview cards, card history. Requires useItemCards context for kanban card data and multiple async API operations.
Recommendation: Retain vendored. Deeply coupled to the item domain and kanban card system. Not a generic grid concern.
#5 — CardCountCell
Section titled “#5 — CardCountCell”What it is: A cell renderer that lazy-loads the kanban card count for each item via useItemCards context.
Recommendation: Retain vendored. Domain-specific, requires API context.
#6 — NotesCell / CardNotesCell
Section titled “#6 — NotesCell / CardNotesCell”What they are: Icon-button cell renderers that open a NoteModal for inline editing of item.notes and item.cardNotesDefault fields.
Recommendation: Retain vendored. Domain-specific, requires modal and API save callbacks.
#7 — itemsColumnDefs
Section titled “#7 — itemsColumnDefs”What it is: 30 column definitions that wire cell renderers, formatters, editors, and header components to the AG Grid. Defined in vendored/arda-frontend/components/table/columnPresets.tsx (~1300 lines).
Why it’s needed: Without column definitions, the grid has no columns.
Recommendation: Fork columnPresets.tsx into canary-refactor/components/columnPresets.tsx. Update imports for any canary cell Display/Editor atoms that replace vendored equivalents. Retain vendored imports for domain-specific renderers (#3-6) and editors (#2).
This is the primary integration point where canary Tier 1 atoms meet vendored domain components. See Appendix A for a column-by-column mapping of which columns can use canary atoms vs which must retain vendored components.
#8 — Draft Lifecycle Management
Section titled “#8 — Draft Lifecycle Management”What it is: ItemTableAGGrid manages a draft lifecycle: creating draft items per row, batching draft saves, tracking unsaved changes via dirty sets, auto-publishing on row leave, and showing row-level saving/error UI states. This is ~400 lines of domain-specific orchestration built on top of ArdaGrid.
Current canary coverage: The useDirtyTracking<T>() hook (Wave 3a) covers generic dirty state tracking (clone row data, track per-cell edits, save/discard drafts). But the draft creation API calls (createDraftItem, updateItem), row-level status UI, and auto-publish logic are items-specific.
Recommendation: Hybrid approach. The canary-refactor ItemTableAGGrid fork will:
- Use
createEntityDataGridShim<T>()(Tier 3b) as its base grid - Compose
useDirtyTracking<T>()for generic dirty state - Retain the domain-specific draft API logic as vendored code within the fork
#9 — Page Chrome Components
Section titled “#9 — Page Chrome Components”What they are: AppSidebar, AppHeader, SidebarProvider, SidebarInset, tab navigation, search bar, column visibility dropdown, action buttons (Add item, Import, Export, Delete).
Recommendation: Retain vendored. These are application-shell components, not grid components. The canary-refactor stories will import them from vendored paths (@frontend/components/*). The grid library has no responsibility for page layout.
#10 — ItemDetailsPanel / ItemFormPanel
Section titled “#10 — ItemDetailsPanel / ItemFormPanel”What they are: The detail-view panel (opened on row click) and add/edit form panel (opened on “Add item” button). The item-detail.stories.tsx story exercises both.
Recommendation: Retain vendored. These are separate UI layers above the grid. The Entity Viewer project (future) will port the detail panel. The form panel is independent of the grid library.
#11 — Color Cell Editor
Section titled “#11 — Color Cell Editor”What it is: An inline <select> element with 10 color options and visual color swatches, built directly into ItemTableAGGrid as a local component (~30 lines). Not an AG Grid cellEditor — it’s rendered via a custom cellRenderer that switches between display and edit mode.
Recommendation: Retain vendored. Domain-specific. The canary enum cell editor is a generic dropdown, not a color-swatch picker.
Summary
Section titled “Summary”| Classification | Count | Items | Action |
|---|---|---|---|
| Missing from scope | 1 | #1 (SortMenuHeader) | Add to Tier 2 Wave 2 |
| Domain-specific (Tier 4) | 7 | #2, #3, #4, #5, #6, #7, #11 | Retain vendored in canary-refactor stories |
| Partially covered | 1 | #8 (Draft lifecycle) | Hybrid: canary generic hooks + vendored domain logic |
| Out of scope (not grid) | 2 | #9, #10 | Retain vendored |
The canary-refactor stories will be hybrid: canary grid infrastructure (Tiers 2-3b) swapped at the ArdaGrid / ItemTableAGGrid level, with vendored components retained for domain-specific cell renderers/editors, column definitions, page chrome, and panels.
Only #1 (SortMenuHeader) requires a change to the design scope. All other insufficiencies are consistent with the project boundary (Tiers 1-3b in scope, Tier 4 domain grids out of scope).
Required Design Updates
Section titled “Required Design Updates”- Add
SortMenuHeaderto the Design Wave 2 table and Component Dependencies table - Add
SortMenuHeaderto the Tier 2DataGrid<T>porting guideline as an internal sub-component - Document the hybrid canary-refactor story architecture in the Porting Strategy section
Design Update Log
Section titled “Design Update Log”The following changes were applied to design.md based on the decisions in the insufficiency table above.
| Decision | Change Applied to design.md |
|---|---|
#1 SortMenuHeader — Agreed | Added SortMenuHeader to Component Dependencies table (Tier 2), Porting Guidelines table, Wave 2 table, and Wave Summary diagram. Updated DataGrid<T> dependencies to include SortMenuHeader. |
| #2 Typeahead editors — Follow Up | Added to new “Follow Up Projects (Out of Scope)” section as F1. |
#3 SelectAllHeaderComponent — Replace with AG Grid native | Updated DataGrid<T> Porting Guideline to configure AG Grid native rowSelection with headerCheckbox: true and selectionColumnDef. Updated Tier 2 summary bullet. |
#4 QuickActionsCell — Follow Up | Added to “Follow Up Projects” as F2. |
#5 CardCountCell — Agreed (retain vendored) | No change needed (consistent with existing scope). |
#6 NotesCell/CardNotesCell — In scope as Memo type | Added MemoCellDisplay and MemoCellEditor to Component Dependencies table, Porting Guidelines table, Wave 1 table, and Wave Summary diagram. Updated Tier 1 summary bullet to include memo. Wave 1 description updated from 5 to 7 types. |
#7 itemsColumnDefs — No explicit decision | No change (recommendation to fork into canary-refactor stands). |
| #8 Draft lifecycle — Follow Up | Added to “Follow Up Projects” as F3. |
| #9 Page chrome — Follow Up | Added to “Follow Up Projects” as F4. |
#10 ItemDetailsPanel/ItemFormPanel — Agreed | No change needed (retain vendored, consistent with scope). |
| #11 Color editor — In scope as Color type | Added ColorCellDisplay and ColorCellEditor to Component Dependencies table, Porting Guidelines table, Wave 1 table, and Wave Summary diagram. Updated Tier 1 summary bullet to include color. |
Appendix A: Column Definition Migration Map
Section titled “Appendix A: Column Definition Migration Map”The forked itemsColumnDefs (canary-refactor/components/columnPresets.tsx) is the primary integration point where canary Tier 1 atoms meet vendored domain components. The canary grid infrastructure (DataGrid<T>, createEntityDataGrid<T>()) is agnostic to which cell components are used — it passes the ColDef[] directly to AG Grid. ColDef.cellRenderer and ColDef.cellEditor accept any React component conforming to AG Grid’s interfaces, so canary atoms and vendored components coexist in the same column definitions array.
The table below maps each of the 30 vendored columns to its migration action.
Columns That Can Use Canary Atoms (~15)
Section titled “Columns That Can Use Canary Atoms (~15)”| Column | Field | Current Renderer/Editor | Canary Atom | Action |
|---|---|---|---|---|
| SKU | internalSKU | Inline text formatter | TextCellDisplay | Replace renderer with canary |
| GL Code | generalLedgerCode | Inline text formatter | TextCellDisplay | Replace renderer with canary |
| Sub-location | locator.subLocation | Direct text | TextCellDisplay | Replace renderer with canary |
| Sub-Type | classification.subType | Direct text | TextCellDisplay | Replace renderer with canary |
| Use Case | useCase | Direct text | TextCellDisplay | Replace renderer with canary |
| Department | locator.department | Direct text | TextCellDisplay | Replace renderer with canary |
| Facility | locator.facility | Direct text | TextCellDisplay | Replace renderer with canary |
| Supplier SKU | primarySupply.sku | Direct text | TextCellDisplay | Replace renderer with canary |
| Min Qty Amount | minQuantityAmount | String number formatter | NumberCellDisplay | Replace renderer with canary |
| Order Amount | orderQuantityAmount | String number formatter | NumberCellDisplay | Replace renderer with canary |
| Taxable | taxable | ”Yes”/“No” | BooleanCellDisplay | Replace renderer with canary |
| Order Method | primarySupply.orderMechanism | Enum label map | EnumCellDisplay / EnumCellEditor | Replace renderer and editor with canary |
| Card Size | cardSize | Enum label map | EnumCellDisplay / EnumCellEditor | Replace renderer and editor with canary |
| Label Size | labelSize | Enum label map | EnumCellDisplay / EnumCellEditor | Replace renderer and editor with canary |
| Breadcrumb Size | breadcrumbSize | Enum label map | EnumCellDisplay / EnumCellEditor | Replace renderer and editor with canary |
Columns Using New Canary Cell Types (~3)
Section titled “Columns Using New Canary Cell Types (~3)”| Column | Field | Current Renderer/Editor | Canary Atom | Action |
|---|---|---|---|---|
| Notes | notes | NotesCell (icon + modal) | MemoButtonCell + createMemoButtonCellEditor() | Replace with canary memo button pattern (vendored-compatible icon + modal). MemoCellDisplay available as alternative for inline truncated display. |
| Card Notes | cardNotesDefault | CardNotesCell (icon + modal) | MemoButtonCell + createMemoButtonCellEditor() | Same as Notes — canary memo button pattern. |
| Color | color | Inline <select> with swatches | ColorCellDisplay / ColorCellEditor | Replace with canary color type |
Hybrid Columns (~1)
Section titled “Hybrid Columns (~1)”| Column | Field | Current Renderer/Editor | Action |
|---|---|---|---|
| Supplier | primarySupply.supplier | Typeahead display + SupplierCellEditor | Canary TextCellDisplay for display; retain vendored SupplierCellEditor for editing |
Columns Retained as Vendored (~10)
Section titled “Columns Retained as Vendored (~10)”| Column | Field | Current Renderer/Editor | Why Not Canary |
|---|---|---|---|
| Item (name) | name | Custom blue clickable text renderer | Custom rendering (clickable, opens detail panel) — not a simple text cell |
| Image | imageUrl | GridImage component | Image cell type deferred to F5 |
| Unit Price | primarySupply.unitCost | formatCurrency (Money type) | No currency/money cell type in scope |
| Order Cost | primarySupply.orderCost | formatCurrency | Same — no currency type |
| Created | createdCoordinates | formatDateTime | Datetime cell type deferred to F5 |
| Lead Time | primarySupply.averageLeadTime | Duration formatter (“N hours”) | No duration cell type in scope |
| Classification | classification.type | ”type - subType” multi-field rollup | Custom multi-field rendering |
| Location | locator.location | ”Facility / Dept / Location” rollup | Custom multi-field rendering |
| Quick Actions | (virtual) | QuickActionsCell | Domain-specific (#4), requires kanban context |
| Card Count | (virtual) | CardCountCell | Domain-specific (#5), requires lazy API fetch |
Column Removed
Section titled “Column Removed”| Column | Current Renderer | Action |
|---|---|---|
| Select (checkbox) | SelectAllHeaderComponent | Removed from column definitions. Replaced by AG Grid native rowSelection configuration (see Appendix A in design.md). |
Copyright: © Arda Systems 2025-2026, All rights reserved