The Factory ledger reads fine at ~45 goods but degrades structurally at late-game Py scale (hundreds of items). Rework the goods sections on TanStack Table (headless — markup, badges, drawer-clicks, and mobile card-stacking stay exactly as they are; only the data model moves).
Problems today
- The deficit sort conflates magnitude with urgency. Everything sorts by absolute net/s, so bulk fluids (
-500 Water) permanently own the top while a fully-starved 0.3/s intermediate that is killing a science chain sits buried. The severity axis that matters is relative: fraction of demand met.
- No sorting controls at all — and the fixed order is backwards for Surpluses (inherits one global ascending-net sort, so the smallest surpluses list first).
- Nothing collapses. Four always-open sections plus Machines means scrolling through everything to reach anything.
actual/s — the "factory is actually dying" signal — is the least prominent column.
Plan
- Add
@tanstack/react-table; shared column defs for the goods sections (name, produced/s, consumed/s, net/s, %-met, actual/s), getSortedRowModel, controlled sorting state.
- Click-to-sort headers with per-section defaults: Deficits by %-met ascending (fully starved first), Surpluses by net descending, Stock buffers by name. Sorting choices persisted (localStorage).
- %-met on deficit rows (produced ÷ consumed, small percent or thin bar) so 0%-starved reads as alarming regardless of magnitude.
- Collapsible sections with counts in the header, remembered state.
- Machines card migrates to the same engine if low-friction, else follows later.
Deliberately deferred: kind/category filter chips and grouping (real but heavier), and @tanstack/react-virtual — the designated escape hatch if row count ever measurably hurts rendering; nothing in this design blocks bolting it on (uniform-height rows).
Bundle size is a non-concern (desktop app; the icon atlas dwarfs the JS).
The Factory ledger reads fine at ~45 goods but degrades structurally at late-game Py scale (hundreds of items). Rework the goods sections on TanStack Table (headless — markup, badges, drawer-clicks, and mobile card-stacking stay exactly as they are; only the data model moves).
Problems today
-500 Water) permanently own the top while a fully-starved 0.3/s intermediate that is killing a science chain sits buried. The severity axis that matters is relative: fraction of demand met.actual/s— the "factory is actually dying" signal — is the least prominent column.Plan
@tanstack/react-table; shared column defs for the goods sections (name, produced/s, consumed/s, net/s, %-met, actual/s),getSortedRowModel, controlled sorting state.Deliberately deferred: kind/category filter chips and grouping (real but heavier), and
@tanstack/react-virtual— the designated escape hatch if row count ever measurably hurts rendering; nothing in this design blocks bolting it on (uniform-height rows).Bundle size is a non-concern (desktop app; the icon atlas dwarfs the JS).