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:
-
Transaction cell never clipped. All the OTHER columns (
Type,Funds Account,Status) setonCell.style = { maxWidth, overflow: 'hidden', textOverflow: 'ellipsis' }. TheTransactioncolumn had noonCellβ so itsMarqueeText/TransactionTitleWithLinksrender could blow past the declared width, forcingscroll.xpast container width, which is what pushed Type / Funds Account / Status / Notes off-frame. -
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
ResizableTitlerequires bothwidthANDonResizeto 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. -
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
ResizeObserveron the existingtableRefwrapper (containerWidthstate). payerPayeeWidthcomputed:max(FLOOR, containerWidth β sum(fixed columns) β scrollbar). Floor = 240px.payerPayeeWidth(NOTcolumnWidths.payerPayee) is the value passed to the Transaction column'swidth/onHeaderCell.width/onHeaderCell.style.maxWidth, and feedsbtScrollX's sum so the table-wide width tracks reality.- Transaction column loses its
onResize/onDoubleClick(it's computed; nothing to drag), which makesResizableTitlecleanly omit the handle for that column. Other columns keep theirs. onCelladded to the Transaction column withstyle: { maxWidth: payerPayeeWidth, overflow: 'hidden' }.MarqueeTextstill scrolls the clipped tail on hover.- Persistence:
localStorage['aote.colw.bankTx.v1']β read on mount, write oncolumnWidthschange. Onlymethod / bank / status / balance / actionsare persisted;payerPayeeis 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 (
isMobilebranch) untouched β it falls back to100%scroll and the existingcolumnWidths.payerPayeefloor, unchanged from before. - Removing the
setColumnWidths((prev) => ({ ...prev, ...titleMinWidths }))rehydrate at ~line 1424. It still overwritespayerPayeewith the title-only width, butpayerPayeeis 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 signalmainπ’ Β·nightlyπ΄ β main only; mirrored totaskboard. - 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 inBankTransactionsTab.tsxwere 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 todone(it had been left atdoingafter landing β surfaced by EOP Local Assistance's status sweep). Branch signalmainπ’ Β·nightlyπ΄ β main only; mirrored totaskboard. - 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 vialocalStorage['aote.colw.bankTx.v1']. - Commit(s):
571dec2a(landed onmain; merge-renumbered T-117 β T-119 viaf842077d). - Verified: the
Build NAS app imagerun for571dec2a(workflow28159571796) 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, commit94722f7c) layered on this same file and the T-119 flex-width machinery (payerPayeeWidth,btScrollX, ResizeObserver, theaote.colw.bankTx.v1persistence, the TransactiononCelloverflow) is all intact and consistent β T-131 did not disturb it. - Blast radius:
components/accounting/BankTransactionsTab.tsxonly. 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").