Skip to content

T 119


uid: T-119 title: BankTransactions table β€” flex Transaction column, persist drag-resize for fixed columns status: done area: accounting-ui created: 2026-06-25 updated: 2026-06-29 renumbered_from: T-117 β†’ T-119 (T-117/T-118 taken by Accounting (Diagnostics) while this was in flight) related: T-104, T-106


Why (owner, 2026-06-25)

Owner-reported recurring layout pain (verbatim):

"After having developed the web app for such a long time, and having it tackled multiple times, I still can't seem to get the column width of all the tables on the accounting page right. For example (not just this one), the bank transactions table pushes the type column, the funds account column, the status: and the comment button column out of frame. Well, even though I understand that some of the transactions has very lengthy names, but the other columns that are pushed to the far right still needs to be all visible and they should be of just the right width (just wide enough to have everything displayed)"

This task covers the BankTransactions table specifically. The same pattern will roll out to the other accounting tables next, after the owner eyeballs the result here.

Root cause (Bank Transactions)

Three co-located issues in components/accounting/BankTransactionsTab.tsx:

  1. Transaction cell never clipped. All the OTHER columns (Type, Funds Account, Status) set onCell.style = { maxWidth, overflow: 'hidden', textOverflow: 'ellipsis' }. The Transaction column had no onCell β€” so its MarqueeText / TransactionTitleWithLinks render could blow past the declared width, forcing scroll.x past container width, which is what pushed Type / Funds Account / Status / Notes off-frame.

  2. Transaction had an explicit fixed width, not a flex one. The pre-existing comment at the column def acknowledged a prior attempt at "no explicit width β€” flexes to fill" had been reverted because antd's ResizableTitle requires both width AND onResize to render the handle β€” so making it flex disabled the handle, and giving it a fixed width brought the handle back but lost the flex behaviour. Both are achievable with a ResizeObserver-driven computed width, but the file had been left at the fixed-width compromise.

  3. No persistence. Drag-resize choices on the fixed-content columns reset on every reload, so even when the owner got it right, it didn't stick β€” a likely contributor to the "I keep re-fixing it" frustration.

What shipped

components/accounting/BankTransactionsTab.tsx:

  • Container width tracked via ResizeObserver on the existing tableRef wrapper (containerWidth state).
  • payerPayeeWidth computed: max(FLOOR, containerWidth βˆ’ sum(fixed columns) βˆ’ scrollbar). Floor = 240px. payerPayeeWidth (NOT columnWidths.payerPayee) is the value passed to the Transaction column's width / onHeaderCell.width / onHeaderCell.style.maxWidth, and feeds btScrollX's sum so the table-wide width tracks reality.
  • Transaction column loses its onResize / onDoubleClick (it's computed; nothing to drag), which makes ResizableTitle cleanly omit the handle for that column. Other columns keep theirs.
  • onCell added to the Transaction column with style: { maxWidth: payerPayeeWidth, overflow: 'hidden' }. MarqueeText still scrolls the clipped tail on hover.
  • Persistence: localStorage['aote.colw.bankTx.v1'] β€” read on mount, write on columnWidths change. Only method / bank / status / balance / actions are persisted; payerPayee is computed each render, never written.

Behavioural delta: - Default view fits in any container β‰₯ ~240 + sum(fixed columns) + 12 px (~540 + 240 β‰ˆ 780px), with all columns visible. The previous default sometimes pushed off-frame depending on the longest transaction title. - Long titles clip with ellipsis (and marquee on hover) instead of pushing the column wider. - Dragging any fixed column wider shrinks Transaction to absorb it (until Transaction hits its 240px floor, at which point horizontal scroll appears β€” same fallback as before, but as a last resort, not the default). - Resized widths persist across reloads.

Verification

  • npx tsc --noEmit -p tsconfig.json β€” 0 errors (clean across the whole project).
  • Owner verifies the rendered behaviour on the live site after the NAS deploy lands. I can't see the browser from this sandbox.

Out of scope for T-119

  • Other accounting tables (Periods, Reimbursements, ReconciliationTab drawers, etc.). They use plain antd Table without the resize machinery β€” different code path. Per the owner's "BankTransactions first, then expand" pick, they're staged for a follow-up task once this lands and the pattern is confirmed.
  • Mobile layout (isMobile branch) untouched β€” it falls back to 100% scroll and the existing columnWidths.payerPayee floor, unchanged from before.
  • Removing the setColumnWidths((prev) => ({ ...prev, ...titleMinWidths })) rehydrate at ~line 1424. It still overwrites payerPayee with the title-only width, but payerPayee is now computed (payerPayeeWidth) every render, so that stale state value is no longer read by any caller β€” it's a harmless dead write. Cleaning it up belongs in the follow-up sweep.

Decision log

2026-06-25 β€” opened + landed (BankTransactions only)

  • βœ… Attestation (Accounting (Infrastructure)): read AGENTS.md; scope-scanned β€” no existing task covers "column-width / overflow on the accounting tables." Branch signal main 🟒 Β· nightly πŸ”΄ β†’ main only; mirrored to taskboard.
  • Source: Accounting (Infrastructure) Β· https://claude.ai/code/session_015P6KzVYsQCLgEmUjR9bMwM
  • Proposed by: the owner ("the bank transactions table pushes the type column … out of frame"). Approved by: the owner via AskUserQuestion β€” "BankTransactions first, then expand" + "Keep [resize handles]" + "Land it, you eyeball".
  • Renumber: opened as T-117, but T-117 (receipt-matched tx display name) and T-118 (vendor template clean-up) were taken by Accounting (Diagnostics) while this was in flight; renumbered to T-119 per the AGENTS.md "whoever merges second renumbers" rule. The six [T-117] markers in BankTransactionsTab.tsx were updated to [T-119] to match.
  • Verified locally: tsc clean (0 errors).
  • Owner verifies live after the NAS deploy ships.

2026-06-29 β€” closed β†’ done (Accounting (Infrastructure))

  • βœ… Attestation (Accounting (Infrastructure)): read AGENTS.md; flipping my own task to done (it had been left at doing after landing β€” surfaced by EOP Local Assistance's status sweep). Branch signal main 🟒 Β· nightly πŸ”΄ β†’ main only; mirrored to taskboard.
  • Source: Accounting (Infrastructure) Β· https://claude.ai/code/session_015P6KzVYsQCLgEmUjR9bMwM
  • Outcome / verdict: shipped as designed β€” the Transaction column flexes to remaining container width (ResizeObserver β†’ payerPayeeWidth), long titles clip with ellipsis instead of pushing the fixed columns off-frame, and drag-resize on the fixed columns persists via localStorage['aote.colw.bankTx.v1'].
  • Commit(s): 571dec2a (landed on main; merge-renumbered T-117 β†’ T-119 via f842077d).
  • Verified: the Build NAS app image run for 571dec2a (workflow 28159571796) went green and deployed. Independently re-confirmed 2026-06-29 during the Codex-commit review: Codex's T-131 (Bank-Tx period scoping + page-size, commit 94722f7c) layered on this same file and the T-119 flex-width machinery (payerPayeeWidth, btScrollX, ResizeObserver, the aote.colw.bankTx.v1 persistence, the Transaction onCell overflow) is all intact and consistent β€” T-131 did not disturb it.
  • Blast radius: components/accounting/BankTransactionsTab.tsx only. The follow-up to extend the same pattern to the other accounting tables (Periods / Reimbursements / drawers) remains not started β€” a separate task when the owner wants it (per "BankTransactions first, then expand").